views:

3337

answers:

3

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?

+3  A: 

You can use:

def init(var=0)
 @var = var
end

And it will default to 0 if you don't pass anything.

If you don't want to have to call it everytime, you could use something like this:

module AppConfiguration
   mattr_accessor :google_api_key
   self.google_api_key = "123456789"
...

end
Brian
So, I still need to call this function before doing anything with the module?
Geo
I added a 2nd way to avoid that problem - its from the rails code
Brian
+1  A: 

for a class, I'd say the following, since the initialize is called whenever you .new a new instance of the class.

def initialize
   @var = 0
end

from Practical Ruby:

It goes on to say that a module's initialize will be called if an including class's initialize calls super, but doesn't mention that this is a consequence of how super works everywhere, not special handling for initialize. (Why might one assume initialize gets special handling? Because it gets special handling with respect to visibility. Special cases create confusion.)

Since its a module, will initialize be called though? That's what my first answer was. I added the second to account for it not being called.
Brian
+6  A: 

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?"
rampion
Somebody's been reading the poignant guide ;)
Adam Lassek
It's been a while, but yeah :). Plus, I feel that all that needs to be said about Messrs Foo and Bar has been said.
rampion
Thank you for your answer.
Geo