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 :somevarreferences 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
will result in the answer you expect.
Related note: you don’t have to declare instance variables in Ruby, you just create them with
@somevartype notation. Theattr_accessormethod 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
afromb, by just doing:But the setter method
somevar=is ambiguous with creating a local variable with the same notation:So to call the somevar setter method you need to explicitly say that you are calling the method on self with:
When you called
send :somevar=,'something'you were invoking the somevar instance method also.