Search code examples
rubymixins

Ruby -- ensuring local variable doesn't collide with method name


I'm trying to slim down my fat models by applying the Single Responsibility Principle. I'm culling out a lot of common code into mixins, which are then included into multiple classes. However, I'm running into this strange problem of local variables colliding with method names (or attr_accessors) of the class which includes the mixin. For example:

module MyAwesomeMixin
  def update_total
    my_total = self.pricing_items.reduce(0) {|sum, x| sum + x} # this borks if the "host class" has a method called my_total=
    total = my_total
  end
end

The code snippet above has complete unintended consequences if the "host class" has a method called my_total= How do I ensure that the my_total variable is completely inside the scope of update_total method and has absolutely nothing to do with the environment around it?


Solution

  • There's something you don't show us. In this case the only "unintented consequence" is that method my_total= is not called, because local var my_total is created.

    module MyAwesomeMixin
      def update_total
        my_total = 10 # !> assigned but unused variable - my_total
      end
    end
    
    class Foo
      include MyAwesomeMixin
    
      attr_accessor :my_total
    end
    
    f = Foo.new
    f.my_total # => nil
    f.update_total
    f.my_total # => nil
    

    If you intend to call the setter, call it on self.

    module MyAwesomeMixin
      def update_total
        self.my_total = 10
      end
    end
    
    f = Foo.new
    f.my_total # => nil
    f.update_total
    f.my_total # => 10