Eu tenho algum código baseado nesta resposta do SO: https://stackoverflow.com/a/2136117/2158544 . Essencialmente, é assim (nota: no código real, eu não controlo o módulo A) :
module A
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def singleton_test
end
end
end
module B
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def self.extended(base)
puts base.method(:singleton_test).owner
define_method(:singleton_test) do |*args, &blk|
super(*args, &blk)
end
end
end
end
Primeira inclusão:
class C
include A
include B
end
A::ClassMethods # <- output
Segunda inclusão:
class D
include A
include B
end
B::ClassMethods # <- output
Embora a chamada para super
ainda seja roteada corretamente para module A
, estou confuso por que singleton_test
já está "embrulhado" quando é incluído em class D
(owner is B::ClassMethods
). Minha teoria é que quando module B
redefines singleton_test
, ele está redefinindo-o no nível do módulo incluído ( module A
) e, portanto, toda vez que module A
é incluído posteriormente, o método já foi "embrulhado".