How can I initialize a module's instance variables in Ruby?

Geo picture Geo · Mar 30, 2009 · Viewed 69.4k times · Source

I have some modules where I would like to use instance variables in. I'm currently initializing them like this:

module MyModule
  def self.method_a(param)
    @var ||= 0
    # other logic goes here
  end
end

I also could call a init method to initialize them:

def init
  @var = 0
end

but this would mean I have to remember to always call it.

Is there a better way of doing this?

Answer

rampion picture rampion · Mar 30, 2009

Initialize them in the module definition.

module MyModule
  # self here is MyModule
  @species = "frog"
  @color = "red polka-dotted"
  @log = []

  def self.log(msg)
    # self here is still MyModule, so the instance variables are still available
    @log << msg
  end
  def self.show_log
    puts @log.map { |m| "A #@color #@species says #{m.inspect}" }
  end
end

MyModule.log "I like cheese."
MyModule.log "There's no mop!"
MyModule.show_log #=> A red polka-dotted frog says "I like cheese."
                  #   A red polka-dotted frog says "There's no mop!"

This will set the instance variables when the module is defined. Remember, you can alwasys reopen the module later to add more instance variables and method definitions, or to redefine existing ones:

# continued from above...
module MyModule
  @verb = "shouts"
  def self.show_log
    puts @log.map { |m| "A #@color #@species #@verb #{m.inspect}" }
  end
end
MyModule.log "What's going on?"
MyModule.show_log #=> A red polka-dotted frog shouts "I like cheese."
                  #   A red polka-dotted frog shouts "There's no mop!"
                  #   A red polka-dotted frog shouts "What's going on?"