In testing a getter/setter pair in a rails model, I've found a good example of behavior I've always thought was odd and inconsistent.
In this example I'm dealing with class Folder < ActiveRecord::Base
.
Folder belongs_to :parent, :class_name => 'Folder'
On the getter method, if I use:
def parent_name parent.name end
...or...
def parent_name self.parent.name end
...the result is exactly the same, I get the name of the parent folder. However, in the getter method if I use...
def parent_name=(name) parent = self.class.find_by_name(name) end
... parent becomes nil, but if I use...
def parent_name=(name) self.parent = self.class.find_by_name(name) end
...then then it works.
So, my question is, why do you need to declare self.method sometimes and why can you just use a local variable?
It seems the need for / use of self
in ActiveRecord is inconsistent, and I'd like to understand this better so I don't feel like I'm always guessing whether I need to declare self or not. When should you / should you not use self in ActiveRecord models?
self is a special variable that points to the object that "owns" the currently executing code. Ruby uses self everwhere: For instance variables: @myvar. For method and constant lookup.
Active Record is the M in MVC - the model - which is the layer of the system responsible for representing business data and logic. Active Record facilitates the creation and use of business objects whose data requires persistent storage to a database.
ActiveRecord is an ORM. It's a layer of Ruby code that runs between your database and your logic code. When you need to make changes to the database, you'll write Ruby code, and then run "migrations" which makes the actual changes to the database.
ActiveRecord::Base indicates that the ActiveRecord class or module has a static inner class called Base that you're extending.
This is because attributes/associations are actually methods(getters/setters) and not local variables. When you state "parent = value" Ruby assumes you want to assign the value to the local variable parent.
Somewhere up the stack there's a setter method "def parent=" and to call that you must use "self.parent = " to tell ruby that you actually want to call a setter and not just set a local variable.
When it comes to getters Ruby looks to see if there's a local variable first and if can't find it then it tries to find a method with the same name which is why your getter method works without "self".
In other words it's not the fault of Rails, but it's how Ruby works inherently.
Hope that helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With