【发布时间】:2011-01-25 12:01:17
【问题描述】:
作为How can I reverse ruby's include function 的后续行动,得到了很好的回答,但事实证明我对真正问题的简化并不意味着该解决方案不适用。
我现在面临这个问题(为了保护身份而改名!):
module OldFormHelpers
def foo
puts "foo"
end
def bar
puts "bar"
end
end
module Helpers
include OldFormHelpers
end
这给了我:
Helpers.instance_methods
=> ["bar", "foo"]
Helpers.ancestors
=> [Helpers, OldFormHelpers]
这是我真的无权修改的代码,没有分叉。
我想做的是创建一个新模块;
module BetterFormHelpers
def foo
puts "better foo"
end
end
这需要删除OldFormHelpers中的行为,然后添加BetterFormHelpers中的新内容
之前的解决方案是像这样使用undef_method:
Helpers.module_eval do
OldFormHelpers.instance_methods do |m|
undef_method(m)
end
end
但是,在包含BetterFormHelpers 之后,Helpers.instance_methods 不包含“foo”。原因在http://ruby-doc.org/core/classes/Module.src/M001652.html进行了解释
使用remove_method 告诉我Helpers 没有“foo”方法,所以我想我需要某种方法从祖先链中删除第一个包含...
这有点长,所以我停止在最后添加这么多的 sn-ps,但我添加了一个 irb 会话,显示 undef/remove 的行为,然后是一个 include。
【问题讨论】:
-
“这是我无权修改的代码”:猴子补丁不是一个选项吗?
-
猴子补丁是一个选项,有点——但是我们替换的模块的工作方式,它定义模块然后包含它们——将代码注入到这个链的某个地方来阻止包括发生。虽然在追求这条线一段时间后,我开始更倾向于这个方向。
标签: ruby class metaprogramming