Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby module_function, invoking module's private method, invoked in class method style on module shows error

test_module.rb

  module MyModule
    def module_func_a
      puts "module_func_a invoked"
      private_b
    end

    module_function :module_func_a

    private
    def private_b
      puts "private_b invoked"
    end
  end

  class MyClass
    include MyModule
    def test_module
      module_func_a
    end
  end

Invoking module function from class

  c = MyClass.new
  c.test_module

Output 1:

$ ruby test_module.rb 
 module_func_a invoked
 private_b invoked

Invoking module function on module in class method style

ma = MyModule.module_func_a

Output 2:

 module_func_a invoked
 test_module.rb:5:in `module_func_a': undefined local variable or method `private_b' for MyModule:Module (NameError)
 from test_module.rb:31

As can be seen from the Output 1 and Output 2 when including the module in a class, no issue occurs when a module's private method gets invoked from a module function while in case when directly invoking the module function on the module in class method style the module's private method, invoked from module function, is not found.

Can anybody make me understand the reason behind above behavior and whether invoking module function (which in turn invokes module's private method) on module in class method style is possible or not? If possible, then what rectifications are required in my code to do the same?

like image 662
Jignesh Gohel Avatar asked Apr 06 '12 11:04

Jignesh Gohel


People also ask

Can Ruby modules have private methods?

Private instance/class methods for modulesDefining a private instance method in a module works just like in a class, you use the private keyword. You can define private class methods using the private_class_method method.

How do you call a method in a module in Ruby?

As with class methods, you call a module method by preceding its name with the module's name and a period, and you reference a constant using the module name and two colons.

What is Module_function in Ruby?

module_function(*args) private. Creates module functions for the named methods. These functions may be called with the module as a receiver, and also become available as instance methods to classes that mix in the module. Module functions are copies of the original, and so may be changed independently.

What is the difference between class and module in Ruby?

What is the difference between a class and a module? Modules are collections of methods and constants. They cannot generate instances. Classes may generate instances (objects), and have per-instance state (instance variables).


1 Answers

It works when you include the module in a class, because then all of the module's methods get included in that class (the self in module_func_a points to MyClass, which has also the private_b method).

In the other situation self points to MyModule, which does not have private_b method. If you wanted it to work both ways, you'd have to either declare private_b as a module method as well, or simply add the line extend self to MyModule, so that all it's methods would become module methods.

like image 67
psyho Avatar answered Sep 22 '22 16:09

psyho