我想写一点“Deprecate-It”库并经常使用“method_added”回调。 但是现在我注意到在包含模块时不会触发此回调。
是否有任何回调或变通方法,以便在某些内容包含到自身时通知类“Foobar”?
用于演示的小 Demo:
# Including Moduls won't trigger method_added callback
module InvisibleMethod
def invisible
"You won't get a callback from me"
end
end
class Foobar
def self.method_added(m)
puts "InstanceMethod: '#{m}' added to '#{self}'"
end
def visible
"You will get a callback from me"
end
include InvisibleMethod
end
[:invisible, :visible, :wont_exist].each do |meth|
puts "#{meth}: #{Foobar.public_method_defined? meth}"
end
结果是:
InstanceMethod: 'visible' added to 'Foobar'
invisible: true
visible: true
wont_exist: false
附加信息:
我真的需要使用像 method_added 这样的钩子(Hook)。
ActiveModel 在运行时通过匿名模块向类添加 public_instance_methods。
最佳答案
问题是包含模块并没有给类添加方法——它只是改变了方法调用链。该链定义了将在哪些类/模块中搜索未为相关类定义的方法。当你包含一个模块时会发生什么是在该链中添加一个条目。
这与在父类(super class)中添加方法完全相同 - 这不会调用 method_added
,因为它未在父类(super class)中定义。如果一个子类可以改变父类(super class)的行为,那将是非常奇怪的。
您可以通过为您的类重新定义 include
手动调用为包含的模块添加的方法来解决此问题:
class Foobar
def self.include(included_module)
included_module.instance_methods.each{|m| self.method_added(m)}
super
end
end
而且它比在 Module
中重新定义 included
方法要安全得多 - 更改范围仅限于您自己定义的类。
关于ruby-on-rails - Ruby method_added 回调不触发包括模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9386179/