0

I'm reading a book about Ruby/Rails and have a question about something simple. In the method "turn" below, the author uses "self," which refers to the class. However, what is the difference (in terms of what you can and cannot do), if any, if he left off "self" and just did

direction = new_direction

Code

class Car << ActiveRecord::Base

  validates :direction, :presence => true 
  validates :speed, :presence => true

  def turn(new_direction) 

    self.direction = new_direction

  end

end
4
  • I'm notnsure why the other answers are ignoring the AR aspect, but your takeaway from those should be that the class methods must be called in order to persist the value. This is a common-enough mistake in Rails code that I'm pointing it in a comment so it isn't lost. Commented Jan 5, 2012 at 2:38
  • Also, note that @direction is different yet again, and will also not be persisted. Commented Jan 5, 2012 at 3:04
  • all of these answers helped me a bit, don't know who to give the check to. Commented Jan 5, 2012 at 3:35
  • Doesn't matter--whichever one provided the most insight. My personal concern is that you understand why self.direction/etc. will update e DB and other forms won't--I don't need anything more than that :) Commented Jan 5, 2012 at 3:40

4 Answers 4

3

Some background: The existence of "self" in ruby just means the current object. You see class methods like this, where the method is defined on the Class, not the Instance.

class Cookbook
  def self.find_recipe
  end
  def is_awesome?
    true
  end
end

This find_recipe is a method on Cookbook, so you call it by Cookbook.find_recipe and you would call is_awesome on an instance by:

cookbook = Cookbook.new
puts cookbook.is_awesome?

So: The reason self.direction= is called is the author does not want to create a variable named direction in the method. If the author had:

class Car
  attr_accessor :direction
  def turn(new_direction)
    direction = new_direction
  end
end

Then you would see:

car = Car.new
car.direction = :left
car.turn(:right)
car.direction
 => :left     

change it to self.direction, and then it will set instance's variable correctly.

Sign up to request clarification or add additional context in comments.

Comments

2

This sets a local variable a to the value of b

a = b

But this is different:

self.a = b

This actually runs the a= method with b as an argument. It actually means:

self.a=(b)

Lastly, while methods can be called on self with providing self as the receiver, the same is not true for assignment. a = b will never invoke the a= method, and will only ever assign a local variable.

Comments

1

ActiveRecord (persisted) vars must be accessed with self because of AR's implementation.

Here, the self distinguishes a column (DB) variable from a "normal", un-persisted instance property. The difference would be that the value wouldn't be saved in the database on a save or update.

Comments

1

See here: http://snippets.dzone.com/posts/show/7963

self.direction = new_direction

Assigns the a new value to the 'direction' attribute on the instance of Car, whereas

direction = new_direction

creates a local variable called 'direction' and returns its value but does not update the Car instance.

So for example I believe the following should happen:

class Car << ActiveRecord::Base

  validates :direction, :presence => true 
  validates :speed, :presence => true

  def turn(new_direction) 
    self.direction = new_direction
  end

  def set_speed(new_speed)
    speed = new_speed
  end
end

alf = Car.new

alf.direction = "North"
alf.speed = 1

alf.turn = "South"
alf.set_speed = 5

> alf.direction
=> "South"

> alf.speed
=> 1

8 Comments

o.k, so the speed of "5" doesn't persist because it wasn't set to a class variable, but then why does "alf.speed" return "1" at the end. What causes "1" to persist if it was originally set using an ordinary variable? can you explain this a bit?
@Michael there's no persistence here, it's a demo of how set_speed doesn't set the persistable column field "speed". Persistence only comes in to play if an AR record is saved or its attributes are updated. See how alf.speed is "1" at the end? That's because set_speed is setting a local "speed", not an instance variable or the column variable.
@DaveNewton thanks i got that, if set_speed sets only a local speed, so is alf.speed = 1 also a local "speed"?
@Michael No, alf.speed is the persisted/DB "speed" value (or would be persisted if "save" or si liar is called, anyway).
@DaveNewton but that was my question, what caused it to persist if it wasn't set using self.speed. It was just set as a regular local variable without self so I didn't understand how it persisted. I guess he just didn't "save" it in this example?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.