Given this code:
class Something
attr_accessor :my_variable
def initialize
@my_variable = 0
end
def foo
my_variable = my_variable + 3
end
end
s = Something.new
s.foo
I get this error:
test.rb:9:in `foo': undefined method `+' for nil:NilClass (NoMethodError)
from test.rb:14:in `<main>'
If attr_accessor creates a method called my_variable (and ..=), why can’t foo find the method? It works if I change it to self.my_variable, but why? Isn’t self the default receiver?
You’re not calling the method there, you’re actually referencing the same variable you’re in the process of defining! This is a little gotcha in Ruby.
What would be better is if you referenced and set the instance variable instead:
Or shorter:
Or you could call the setter method, as you found (and Jits pointed) out:
This last one will call the
my_variable=method defined by theattr_accessor, where the other two will only modify a variable. If you did it this way, you could overridemy_variable=to do something different to the value passed in:BONUS
Or you could call the method explicitly by passing an empty set of arguments through:
This is not “The Ruby Way” to go about it, but it’s still interesting to know that you can still call a method this way if you have a local variable of the same name.