Class instance variable for ruby modules

Sorry if the title is a bit misleading, but this post talks about the scenario such that I have several classes, all extending the same module, and I need to avoid using shared or class variables (@@) in the module because the classes extending the module may change the shared or class variable at the same time and cause problem.

So basically we have:

class Test

  extend TestModule

end

class TestTwo

  extend TestModule

end

module TestModule

  @@val

  def somemethod

     #do something with @@val

  end 

end 

And the goal is the replace the @@val class variable with a class instance variable so that if the Test.somemethod and TestTwo.somemethod happens at the same time, there won’t be any problem.

The easiest way (I can think of) of doing this is to set the variable within the class, instead of setting it in the module. For example:

class Test

  @val = “abc”

  class << self; attr_accessor :val; end

  extend TestModule

end 

But the problem of doing this is that everybody else using TestModule will need to update their code after this update, which is unacceptable.

Is there a way to move the variable definition and accessor to the module and has exactly the same effect as defining them in the class? Yes. define the self.extended(base) method.

module TestModule

  def self.extended(base)

    class << base; attr_accessor :val; end

    base.val = “abc”

  end

  def somemethod

     #do something with self.val

  end 

end

class Test

  extend TestModule

end

 

Here base refers to the class extending this module. self. extended is called when the module is initialized, and the accessors for the base class is then created (class << base; attr_accessor :val; end), base.val = abc sets the default value.

By doing it this way, the module works exactly the same as before, and multiple classes can extend it and call the same method without affecting each other.

Hope this helps.

3 thoughts on “Class instance variable for ruby modules

Leave a Reply

Your email address will not be published. Required fields are marked *