Some Guy
Some Guy

Reputation: 13568

What's the difference between using self.attribute and attribute in a model?

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

Answers (5)

user229044
user229044

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

Alok Anand
Alok Anand

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

Prasad Surase
Prasad Surase

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

Pavel Pachkovsky
Pavel Pachkovsky

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

lalameat
lalameat

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

Related Questions