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.
精彩评论