Ruby: access to attr_accessor's method from internal method
-
13-06-2021 - |
Frage
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?
Lösung
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.
Andere Tipps
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'
.