Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top