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



Question:

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?


Solution:1

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?"  


Solution:2

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  


Solution:3

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.)


Solution:4

Apparently it's bad form to initialise instance variables in a module in Ruby. (For reasons I don't fully understand, but pertaining to the order in which things are instantiated.)

It seems that best practice is to use accessors with lazy initialisation, like so:

module MyModule    def var      @var ||= 0     end  end  

Then use var as the getter for @var.


Solution:5

i answered a similar question, you can set class instance variables doing this

module MyModule    class << self; attr_accessor :var; end  end    MyModule.var  => nil    MyModule.var = 'this is saved at @var'  => "this is saved at @var"    MyModule.var      => "this is saved at @var"  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »