As a follow up to How can I reverse ruby's include function, which was well answered but turned out my simplification of the real problem mean't that the solution was not applicable.
I'm now faced with this (names changed to protect identities!):
module OldFormHelpers
def foo
puts "foo"
end
def bar
puts "bar"
end
end
module Helpers
include OldFormHelpers
end
This gives me:
Helpers.instance_methods
=> ["bar", "foo"]
Helpers.ancestors
=> [Helpers, OldFormHelpers]
This is code that I don't really have access to modify, without forking.
What I want to do is create a new module;
module BetterFormHelpers
def foo
puts "better foo"
end
end
This needs to remove the behaviours from OldFormHelpers
, and then add in the new stuff from BetterFormHelpers
The previous solution was to use undef_method
like so:
Helpers.module_eval do
OldFormHelpers.instance_methods do |m|
undef_method(m)
end
end
However, after including BetterFormHelpers
, Helpers.instance_methods doesn't contain "foo". The reason for this is explained at http://ruby-doc.org/core/classes/Module.src/M001652.html
Using remove_method
tells me that Helpers
doesn't have the "foo" method, so I guess I need some way of removing the first inclusion from the ancestors chain...
This was getting a bit long so I stopped putting so many snippets in towards the end, but I add an irb session showing the behaviour of undef/remove and then an include.
Can't you undefine only the methods that will not be overwritten?
Helpers.module_eval do
(OldFormHelpers.instance_methods - BetterFormHelpers.instance_methods).each do |m|
undef_method(m)
end
end
(The latter included module will be searched first so that no OldFormHelpers method will be executed if BetterFormHelpers also defines it.)
If you want to dynamically overwrite further methods of the OldFormHelpers module, however, the problem remains the same.
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