TL; DR - вы вообще не можете, но Base1.include Patch
может быть достаточно хорошим.
Для вашего примера кода ancestors
из Base1
и Base2
: (выровнено для ясности)
Base1.ancestors #=> [Base1, Feature, Object, Kernel, BasicObject]
Base2.ancestors #=> [Base2, Patch, Feature, Object, Kernel, BasicObject]
Base2
имеет дополнительного предка Patch
перед Feature
- результат Feature.prepend Patch
.
Rubyне позволяет нам свободно изменять цепочку предков модуля, поэтому мы не можем просто добавить Patch
к Feature
задним числом.
Но, к счастью, Patch
является первым модулем после Base
класс, поэтому мы можем прибегнуть к include
, чтобы добавить Patch
к Base1
вместо:
Base1.include Patch
Base1.ancestors #=> [Base1, Patch, Feature, Object, Kernel, BasicObject]
Очевидно, это работает только для очень конкретных случаев, а не в целом.
Вот контрпример:
module Feature
def action ; 'Feature' ; end
end
module Foo
def action ; "#{super} overridden" ; end
end
module Patch
def action ; 'Patch' ; end
end
class Base1
include Feature
include Foo
end
Feature.prepend(Patch)
class Base2
include Feature
include Foo
end
Base1.new.action #=> "Feature overridden"
Base2.new.action #=> "Patch overridden"
Base1.include Patch
Base1.new.action #=> "Patch"
Глядя на предков, выявляется проблема:
Base1.ancestors #=> [Base1, Foo, Feature, Object, Kernel, BasicObject]
Base2.ancestors #=> [Base2, Foo, Patch, Feature, Object, Kernel, BasicObject]
Base1.include Patch
Base1.ancestors #=> [Base1, Patch, Foo, Feature, Object, Kernel, BasicObject]
Patch
и Foo
не в порядке.