Reputation: 13568
In Ruby on Rails, what's the difference between using self.attribute and attribute in a model?
In this example, assume my_attr is an attribute of the user that gets stored in the database.
class User < ActiveRecord::Base
def do_something!
self.my_attr = 123
end
def do_another_thing!
my_attr = 456
end
end
Upvotes: 24
Views: 14117
Reputation: 239240
The difference in your examples is that the first one works, the second doesn't.
Your second version isn't doing anything (at least nothing meaningful). Writing my_attr = 123
is not equivalent to self.my_attr = 123
. Instead it's creating a local variable called my_attr
and setting it to 123
, and then immediately reaching the end of the method and throwing my_attr
away. The whole method is essentially a no-op, and it doesn't affect the model's my_attr
value in any way.
class User < ActiveRecord::Base
def do_another_thing!
my_attr = 456
puts self.my_attr # nil (or whatever value it was before)
end
end
Conversely, if you want to access a method defined on an object, you can (and should) omit self
:
class User
def name=(value)
@name = value
end
def name
@name
end
def age=(value)
@age = value
end
def age
@age
end
def do_something
self.name = "bob" # self is required
puts name # bob (self.name)
age = 47 # @age is unaffected
age # 47 (local variable), but self.age is nil
end
end
Note that, this isn't a Rails question, it's a Ruby question. There is no Rails-specific code here, this behaviour is part of how Ruby's syntax works.
Upvotes: 30
Reputation: 3356
The keyword self in Ruby gives you access to the current object – the object that is receiving the current message.
So self.attribute
refers to current object's attribute
, where as simply attribute
is there with its scope
.
Read this guide self for more detailed info.
Upvotes: 0
Reputation: 6574
the general rule is, whenever you are modifying self by assigning value to some attribute, use 'self' explicitly
self.first_name = 'Prasad' #if self isnt used, it will create a local variable.
and if you are referencing that attribute(but not modifying), dont use 'self'
def name
name.camelize
end
----UPDATE-----
whenever we access any attribute, ruby will check if getter (reader) and setter (writer) methods for that attribute are defined or not.
So in the above case(when you are assigning a value to attribute), you arent accessing the attribute directly but passing value to the setter which will internally assign the value to the attribute.
2.1.0p0 :008 > User.first.first_name
=> "Prasad"
2.1.0p0 :009 > (User.first.methods - Object.methods).include? :first_name
=> true
2.1.0p0 :010 > (User.first.methods - Object.methods).include? :first_name=
=> true
You can try it by adding a method to the any model
def some_name
first_name = 'Some name'
puts self.first_name
self.first_name = 'Random Username'
puts self.first_name
end
and reload the console and do
2.1.0p0 :017 > User.first.some_name
Prasad
Random Username
=> nil
Upvotes: 4
Reputation: 371
In this case there is no difference. But assume that you have a local variable in a method definition:
def do_something!
self.my_attr = 123
end
def do_another_thing!(my_attr)
puts "my_attr is #{my_attr}"
puts "self.my_attr is #{self.my_attr}"
end
do_something!
do_another_thing!(456)
Then the output would be
my_attr is 456
self.my_attr is 123
self
represents an object. When you call method on self
you call method specifically on that object.
Upvotes: 1
Reputation: 754
do_something! is a instance method. So here the self is the User instance, my_attr= is your User instance's method. The function is to assign a value to user instance variable @may_attr.
In "do_another_thing!", my_attr could be a variable you just declared.
Upvotes: -1