If a class includes many modules, and the methods gained from the include call private methods from their originating modules, and private methods exist in other modules with the same name, it should use the definition from its own module. In code:
module C
def c
puts collision
end
private
def collision
'c'
end
end
module B
def b
puts collision
end
private
def collision
'b'
end
end
class A
include B
include C
end
A.new.b
# => 'c'
I expected A.new.b
to give 'b'
and A.new.c
to give 'c'
but there is collision because they use the same private method name. In large projects with many includes, how is this avoided?
I assume the real question is: how do I ensure that the my modules are not using other modules methods, which (which accidentally have the same name).
It's best if you can make sure that your module methods are not state dependent and define them as module method and use them this way. So you explicitly use any helping
methods like this:
module C
def c
puts C.collision
end
def self.collision
'c'
end
end
module B
def b
puts B.collision
end
def self.collision
'b'
end
end
class A
include B
include C
end
A.new.b # b
A.new.c # c
If you want to make them private, there's some extra code to put there, you can read a clear article about it: https://6ftdan.com/allyourdev/2015/05/02/private-module-methods-in-ruby/
As stated in this answer there's not magic you can turn on to make it work. Include mechanism is quite simple and (IMO) it should stay that way. As you are aware of this collision problem - you can now avoid it.
In case you don't like this approach, you can also encapsulate the real work in a class and use module just for inclusion:
module C
def c
MyLibStuff::ClassDoingRealWork.no_collision_here_anymore(any, param, if_needed)
end
end
You expect some magic, which is not there.
include
is a plain old good mixin. Once called, it just “inserts” all the methods declared in the included module into the module that calls include
.
Hence you end up with something like:
class A
public
def c; ... end
private
def collision; ... end
public
def b; ... end
private
def collision; ... end
end
And the latter private method collision
obviously overrides the former one due to ruby open classes concept.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With