I have a code:
class A
attr_accessor :somevar
def a
somevar = 'something'
puts @somevar
end
def b
send :somevar=, 'something'
puts @somevar
end
end
A.new.a #=> nil
A.new.b #=> 'something'
Why is there a difference? Why can't I just assign an instance variable through a writer? But why local variable has been created instead of method (setter) has been called?
attr_accessor :somevar references the instance variable @somevar. Instance variables must be preceded by the @ sign. All other variables like 'somevar' without an @ sign in a method are just local variables to that method or scope, not instance variables for the object.
Thus, changing the first line in method "a" to
@somevar = 'something'
will result in the answer you expect.
Related note: you don't have to declare instance variables in Ruby, you just create them with @somevar type notation. The attr_accessor method creates setters and getters for that instance variable.
Methods in Ruby are attached to objects, so in order for class A to invoke its own somevar setter method, you would need to write self.somevar = 'something', otherwise the Ruby parser thinks you are just creating a local variable.
This could be confusing because you could invoke method a from b, by just doing:
def b
send :somevar=,'something'
puts @somevar
a # would invoke its own method 'a'
end
But the setter method somevar= is ambiguous with creating a local variable with the same notation:
somevar='something' # Ruby assumes you want to create a local variable
So to call the somevar setter method you need to explicitly say that you are calling the method on self with:
self.somevar = 'something'
When you called send :somevar=,'something' you were invoking the somevar instance method also.
It's because method a is creating a local variable called somevar. It's just one of Ruby's little quirks. You can get around this by doing self.somevar = 'something' or @somevar = 'something'.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With