Question: when do I need to use self in my models in Rails?
I have a set
method in one of my models.
class SomeData < ActiveRecord::Base def set_active_flag(val) self.active_flag = val self.save! end end
When I do this, everything works fine. However, when I do this:
class SomeData < ActiveRecord::Base def set_active_flag(val) active_flag = val save! end end
The active_flag value doesn't change, rather it fails silently. Can someone explain?
I can't find any duplicates, but if someone finds one that's fine too.
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.
The keyword self in Ruby enables you to access to the current object — the object that is receiving the current message. The word self can be used in the definition of a class method to tell Ruby that the method is for the self, which is in this case the class.
the method self refers to the object it belongs to. Class definitions are objects too. If you use self inside class definition it refers to the object of class definition (to the class) if you call it inside class method it refers to the class again.
When you're doing an action on the instance that's calling the method, you use self.
With this code
class SocialData < ActiveRecord::Base def set_active_flag(val) active_flag = val save! end end
You are defining a brand new scoped local variable called active_flag, setting it to the passed in value, it's not associated with anything, so it's promptly thrown away when the method ends like it never existed.
self.active_flag = val
However tells the instance to modify its own attribute called active_flag, instead of a brand new variable. That's why it works.
This happens because of scoping. When you're inside of a method and you try to set a new variable like this:
class SomeData < ActiveRecord::Base def set_active_flag(val) active_flag = val end end
You are creating a brand new variable that lives inside of set_active_flag. As soon as that's done executing, it goes away, not altering self.active_flag
(the actual instance variable) in any way.
HOWEVER (this was a source of confusion for me): when you try to read an instance variable in ruby, like this:
class SomeData < ActiveRecord::Base def whats_my_active_flag puts active_flag end end
You'll actually get self.active_flag
(the actual instance variable) returned.
Here's why:
Ruby will do what it can to avoid returning nil
.
active_flag
exist within the scope of whats_my_active_flag
? active_flag
exist within this scope?However, if you define active_flag
within the whats_my_active_flag
, and then ask for it, it goes through the steps again:
active_flag
exist within the scope of whats_my_active_flag
?In either case, it won't change the value of self.active_flag
unless you explicitly tell it to.
An easy way to describe this behavior is "it doesn't want to disappoint you" and return nil
-- so it does its best to find whatever it can.
At the same time, "it doesn't want to mess up data that you didn't intend to change" so it doesn't alter the instance variable itself.
Hope this 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