Reputation: 6552
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?
Upvotes: 9
Views: 6770
Reputation: 7212
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.
Upvotes: 8
Reputation: 36120
module_function
does copy your module_func_a
into the metaclass but not its dependencies.
So when calling module_func_a
from an object, you get the other method private_b
. But calling it on the module itself fails because private_b
is not a module function.
You should use module_function for private_b
too and it should work.
Upvotes: 3