Reputation: 221
I am just trying to understand the behaviour of the destroy
method in the following code:
UPDATE : Please note my intention is to understand the behaviour, not the immediate solution for assigning nil to the variable.
def conf
@conf ||= { 'foo' => { 'bar' => 'baz' } }
end
def destroy
conf = nil
end
def change
conf['foo']['bar'] = 'meh'
end
def add
conf['foo']['abc'] = 'moo'
end
Here is the output for invoking the add
method:
add
pp conf
# {"foo"=>{"bar"=>"baz", "abc"=>"moo"}}
change
method
change
pp conf
# {"foo"=>{"bar"=>"meh"}}
destroy
method
destroy
pp conf
# {"foo"=>{"bar"=>"baz"}}
So, why doesn't destroy
result in conf
having nil
?
Another related snippet, this time with a scalar not a hash:
def foo
@foo ||= "bar"
end
def destroyfoo
foo = nil
end
def changefoo
foo = "baz"
end
Result when calling changefoo
and destroyfoo
both:
destroyfoo
puts foo
# "bar"
...
changefoo
puts foo
# "bar"
Any pointers on what might be happening would be useful in both cases.
Upvotes: 3
Views: 66
Reputation: 66293
Your destroy
, destroyfoo
and changefoo
methods are all just assigning to a local variable and do not result in a call to the accessor method.
The reason that the change
method works is because conf['foo']['bar'] = 'meh'
is a call to the conf
method to get @conf
, then a call to the []
method on the object returned, then a call to the []=
method on the first level hash. Likewise for add
.
This is different to a direct assignment like conf =
Also, for completeness, note that even if you'd created an attr writer for @conf
(either using attr_writer
or by writing a conf=
method yourself) then a line like conf = nil
would still be referring to a local variable and wouldn't call your method. You'd need to use self.conf=
in order to disambiguate.
Upvotes: 2
Reputation: 17179
It is because your destroy
method is creating a variable named conf
. Ruby is able to tell what is a method and what is a variable based on how you call it.
irb> puts "Lincoln"
Lincoln
irb> puts = "Washington"
irb> puts "Polk"
Polk
irb> puts puts
Washington
What happened here is there is a method called puts
and there is a variable called puts
. Ruby determines which you are trying to use based on how you are calling it. In the last example, the left puts
is the method call while the right puts
is the variable.
Note that the variable destroy
creates will drop out of scope once the method block is done executing. So, in your case, trying to call conf
anytime outside of a method (on the main scope) will be a call to the method.
Upvotes: 1