'Avoid calling private method from module
Is there any possibility to make private method in module ? I want to prevent to call method from other modules.
module A
private
def name # this method can be used in module B
"name"
end
end
module B
def print_name
puts name
end
end
module C
include A
include B
end
class Z
include C
end
Z.new.print_name # want to throw NoMethodError
Solution 1:[1]
You could write the following.
module A
def name
"name from A"
end
end
module B
def print_name
"name from B"
end
end
module C
include A
include B
def self.included(klass)
B.instance_methods(false).each { |m| klass.send(:private, m) }
end
end
class Z
include C
def test
print_name
end
end
Then
Z.instance_methods.include?(:name)
#=> true
Z.private_instance_methods.include?(:print_name)
#=> true
z = Z.new
#=> #<Z:0x00007fb0f810ad28>
z.name
#=> "name from A"
z.print_name
#=> NoMethodError: private method 'print_name' called for #<Z:0x00007fb0f810ad28>
z.test
#=> "name from B"
See Module#included. This is one of several so-called "hook methods".
Suppose Z were as follows.
class Z
def print_name
"name from Z"
end
include C
def test
print_name
end
end
Then
z.print_name
#=> NoMethodError: private method 'print_name' called for #<Z:0x00007fb0f810ad28>
z.test
#=> "name from Z"
This demonstrates that it is the original public method Z#print_name has been made private. Note:
C.ancestors
#=> [Z, C, B, A, Object, Kernel, BasicObject]
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
