garythegoat
garythegoat

Reputation: 1587

Using helper methods in Ruby modules

I'm having some trouble understanding how to incorporate my own helper methods into a Ruby module.

My code:

module MyModule
  def self.foo
    bar
  end

  def bar
    # helper for MyModule.foo
  end
end

MyModule.foo
#=> NameError: undefined local variable or method `bar' for MyModule:Module

I'm not sure why MyModule cannot recognize the bar method. What aspect of scope in Ruby am I being oblivious to?

Upvotes: 2

Views: 5016

Answers (3)

ricktap
ricktap

Reputation: 116

You are trying to call an instance method from a class method. You would have to write

module MyModule
  def MyModule.foo
    MyModule.bar
  end

  # Or you can have it this way
  def MyModule::bar
    # helper for MyModule.foo
  end
end

MyModule.foo

to get what you want.

Upvotes: 1

nitinr708
nitinr708

Reputation: 1467

You're missing the scope of a method (module as well as instance) and basically it's lifecycle..

Module method way: - Following is how you define the module with module methods.

 module MyModule
    def self.foo
        puts "called self.foo"
        bar
    end

    def self.bar
        puts "self.bar got called"
        # helper for MyModule.foo
    end
end

Now, This way, you do not have to instantiate any object to call those methods.. Here is how you would call the methods (one inside the other)

MyModule.foo

Using a class to instantiate the Module and calling methods will not work as they are not instance methods.

Output -

called foo
bar got called

Instance method way: - Following is how you'll define the module with instance methods so that they will work between classes and objects..

module MyModule
  def foo
      puts "called foo"
      bar
  end

  def bar
    puts "bar got called"
    # helper for MyModule.foo
  end
end

class TestModule
  include MyModule
end

Choosing to use the module methods this way you have to call the methods inside module as per below -

#instantiating module MyModule via class
myinstance = TestModule.new
myinstance.foo

Output -

called foo
bar got called

Upvotes: 0

Amit Joki
Amit Joki

Reputation: 59252

Modules can be integrated into classes as mixins. So, you need to include it in a class so it can be used with instance of that class.

As of now, you can make bar as your module method so it can be accessed as is.

module MyModule
  def self.foo
    bar
  end
  def self.bar
     puts "Now it works"
  end
end
MyModule.foo #=> Now it works

Ruby Docs

A Module is a collection of methods and constants. The methods in a module may be instance methods or module methods. Instance methods appear as methods in a class when the module is included, module methods do not.

Upvotes: 4

Related Questions