开发者

What is the difference between referencing object.id vs object[:id] when you return a Model dataset?

I am in the Console environment busy reading all the rows from a table into a variable and I noticed that you can reference the results by specifing my_object.id OR my_object[:id].

Can someone tell me if there is a specific reason for this? Is one of these 'methods' deprecated or what is the reason for this?

Here is a code snippit: (assuming all has been set)

my_object = MyModel.find(:all)
my_object[1].id #returns => 'my value'
my_object[1][:id] # also returns => 'my value'

Which of these methods are best practice? Or is it purely a notation prefe开发者_如何学JAVArence?


you should use

my_object[1].id

"id" is an instance method generated by rails in the MyModel class and it has its corresponding "id=" setter instance method (yes, it's a method)

in the other hand

my_object[1][:id] or my_object[1]["id"] 

will access the @attributes hash directly:

    def read_attribute(attr_name)
      attr_name = attr_name.to_s
      if !(value = @attributes[attr_name]).nil?
      ......
    end

I'd like you to see this code

def [](attr_name)
   read_attribute(attr_name)
end

my_object[1][:id]

If you see the signature of the [] method maybe you'd think that you can call the method like this:

my_object[1][](:id)

but you can't do that because Ruby makes some trickery behind the scenes to make it appear just like if you were accessing a normal array (just like php, js, etc does it), don't get confused.


It's a way of doing a read_attribute, which is protected, outside of the class. From the ActiveRecord::Base source code:

# Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example,
# "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)).
# (Alias for the protected read_attribute method).
def [](attr_name)
  read_attribute(attr_name)
end

model.attribute is the most common way of doing it. The [] method obviously works well if the name of the attribute is stored in a variable.


I'd use model.attribute, it's both more standard and allows you flexibility if you need to override it:

u = User.first
u.identity_url
=> nil
class << u
  def identity_url
    read_attribute(:identity_url) || "undefined"
  end
end
=> nil
u.identity_url
=> "undefined"
u[:identity_url]
=> nil

Kind of a lame example, but you get the idea.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜