Private Module Methods in Ruby

Private module methods in Ruby

I think the best way (and mostly how existing libs are written) to do this is by creating a class within the module that deals with all the logic, and the module just provides a convenient method, e.g.

module GTranslate
class Translator
def perform(text)
translate(text)
end

private

def translate(text)
# do some private stuff here
end
end

def self.translate(text)
t = Translator.new
t.perform(text)
end
end

Accessing Private Methods from Module Functions in Ruby

module_function(symbol, ...) → self says:-

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. The instance-method versions are made private. If used with no arguments, subsequently defined methods become module functions.

You need to make sure you declare the helper method as a #private_class_method: private only affects instance methods.

module Party

def enjoy
puts 'hello'
end

def pooper
enjoy
end

private_class_method :enjoy
module_function :pooper
end

Party.pooper # => 'hello'
Party.enjoy # => private method `enjoy' called for Party:Module (NoMethodError)

Furthermore, you should be careful about the ordering of accessibility keywords like public, private, and module_function. These do not overlap, but rather override.

module Party
module_function # Module function declarations begin
def pooper
bar
end
def bar
enjoy
end

private # Private declarations begin, module function declarations end
module_function # Private declarations end, module function declarations begin
def enjoy # Therefore, this is a module function
"Wahoo!"
end
end

Party.pooper # => "Wahoo!"
Party.bar # => "Wahoo!"
Party.enjoy # => "Wahoo!" <-- No longer private

Note here module_function overrides the previous private declaration.


Here some more examples when module_function will do its job, and when not.

The module_function definitions stop once another accessibility keyword pops up. In this example, module_function is interrupted by public making #pooper a public instance method. Use of private would similarly block module_method.

module Party
module_function
public
def pooper
"i am pooper"
end
end

Party.pooper
# undefined method `pooper' for Party:Module (NoMethodError)

Now if the order is changed:

module Party
public
module_function
def pooper
"i am pooper"
end
end

Party.pooper # => "i am pooper"

Private module method accessible by module classes

Modules in ruby are just containers for methods and constants. Classes know nothing about the modules that they form part of and don't inherit from them. so there is no way to make a method on ´Foo´ available for all the classes that may be inside it.

This approach may give you what you want.

module Foo
module CommandRunning
def execute(*args)
# ...
end
end

class Bar
include CommandRunning

def initialize
execute('initialize', 'bar')
end
end
end

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

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.

Private class (not class method) in a Ruby module?

I haven't seen such concept so far in Ruby, but I guess you could simulate that by creating private method which would return a class created as a local variable (remember that in Ruby, a class is an object just like any other, and can be instantiated in a method and returned by it).

BTW, even private methods in Ruby aren't as private as in other languages - you can always access them using send method. But doing that implies you know what you are doing.

How to test private helper(module) method in rspec

create a dummy class and access private method using .send(:private_method, args)

example

obj = Class.new { extend AppHelper }
obj.send(:sum, 1,2)

Overriding 3rd party private method in ruby module?

It’d be a hacky, but working approach:

ThirdPartyGem::SeeminglyUntouchable.send(
:undef_method, :hidden_interface)
ThirdPartyGem::SeeminglyUntouchable.send(
:define_method, :hidden_interface, ->(chunky){ chunky.upcase })
ThirdPartyGem::SeeminglyUntouchable.send(
:private, :hidden_interface)


Related Topics



Leave a reply



Submit