ActiveRecord accessor dot(.) vs bracket([])
Asked Answered
D

2

9

With Active Record, we can access a value like

method access

user = User.find(1)
user.name #=> 'John'

or

hash access

user[:name] #=> 'John'

I just wonder when to use which, or is there any best practice out there? Personally I'd prefer method access because I feel that is more like ruby way. However when I see code by others, I face the hash access.

Dairen answered 23/11, 2016 at 12:54 Comment(0)
S
6

Rails convention is to use ActiveRecord::AttributeMethods::Read#read_attribute (dot notation), rather than its alias ActiveRecord::AttributeMethods#[], which:

Returns the value of the attribute identified by attr_name after it has been typecast (for example, “2004-12-12” in a date column is cast to a date object, like Date.new(2004, 12, 12)). It raises ActiveModel::MissingAttributeError if the identified attribute is missing.

Superiority answered 23/11, 2016 at 12:58 Comment(8)
Thanks for the answer. So you mean whenever I access with the #[], some typecast is occurred based on the column type. And if I didn't specify with attr_name, it raises an error.Dairen
@Dairen I've edited the answer a bit. Basically two methods are interchangeable, it's just that convention advices the first one :)Superiority
okay, now I got that. I just wonder there are any cases that #[] would be better than dot notation. Maybe readability or something?Dairen
Difference would be, for example, that dot notation would raise an exception undefined method if you call non-existing method on an object, whereas [:] will just return nil (no exceptions). My personal preference is after dot notation especially because of readability :)Superiority
yep so the dot notation has basically two advantages 1. Ruby convention 2. readability. This is the last question, if I access data with method chain. You still use dot notation or [:] For example user.account.uuid or user[:account][:uuid]? pretty much personal preference?Dairen
@Dairen sure, convention remains for any amount of methods in the method's chain (so user.account.uuid) :)Superiority
Thank you for the answer :)Dairen
In addition to what is mentioned above: Bracket notation is easier if you want to dynamically specify which attribute you are reading, such as myobj[attr_to_fetch]. However, dot notation makes it a bit easier to use Safe Navigation, such as myobj&.some_attr. Doing the same in bracket notation is visually noisier: myobj&.[](:some_attr).Repulsive
P
3

I would strongly advise against using bracket notation as it breaks the inheritance hierarchy of method calls and makes refactoring harder.

If my model has an attribute name, and I decide I want to enhance the name every time someone reads it, a very idiomatic way to do that would be:

def name "Awesome #{super}!" end

Any place in my app that uses the method version would work fine, any place that uses the [] notation would return raw database data. I could overwrite the [] but then I would need special conditions checking for specific attributes. The whole thing would be a nightmare.

Another scenario, let's say I had an attribute that used to be stored in the database, but after a while decide that it should be computed on the fly, and end up dropping the database column. With the method version all I would need to do is add methods to my model. With the [] notation the process would be much much harder.

Also [] provides an insignificant performance improvement so though it looks like it's "closer" to the raw data it really isn't.

Primine answered 14/9, 2017 at 21:32 Comment(1)
This question is the top response on Google right now and I don't think the accepted answer is technically correct. This answer is more correct. Bracket notation will return what's in the database, that's a very key difference to dot notation.Ringe

© 2022 - 2024 — McMap. All rights reserved.