1

I was confused about the different ways to access instance variables in rails models. For example, this will work:

def add_calories(ingredient)


    self.total_calories += ingredient.calories

    p total_calories

end

However this will results in errors:

def add_calories(ingredient)

    total_calories += ingredient.calories

end



Error: NoMethodError: undefined method "+" for nil:NilClass

Also this won't work either.

def add_calories(ingredient)

    total_calories = total_calories + ingredient.calories

end

If I can access the instance variable without self in the first case, how come that in the second case, total_calories becomes nil?

Could it be that the default value for total_calories is set to 0? However if that's the case, why does self.total_calories work?

t.integer  "total_calories", default: 0 

I read this post but it doesn't really explain why the third case won't work.

Thanks a lot.

2
  • Not so much instance variables here as accessible attributes. All attributes are contained in an instance_variable called @attributes which is actually a Hash as for why you have to call the getter methods with an explicit receiver I am not sure maybe someone else can assist with that part Commented Jul 18, 2016 at 20:55
  • It works in the first case without an explicit receiver "self" when I used it in a print statement. So that makes me think that self is optional. However in the second and the third case, it wouldn't work without self. Commented Jul 18, 2016 at 21:02

1 Answer 1

1

This seems like less of a question about instance variable access in Rails and more a question about "setter" methods in Ruby (in your case, using the total_calories= method). Information about why an explicit self receiver is needed for setter methods is covered in other Stack Overflow answers, like this one.

In summary, though, the issue is that the intention of the statement total_calories = something could be ambiguous: are you defining a new local variable or calling the setter? Calling self.total_calories = something explicitly says you want to call the setter, while leaving off self and calling total_calories = something says you want a new local variable.

I think your third example should work if you change the method content to use both getter and setter methods explicitly:

def add_calories(ingredient)
  self.total_calories = total_calories + ingredient.calories
end
Sign up to request clarification or add additional context in comments.

Comments

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.