Ruby method_added回调不包括模块

Der*_*don 5 ruby ruby-on-rails callback

我想写一点"Deprecate-It"lib并且经常使用"method_added"回调.但是现在我注意到,当包含模块时,不会触发此回调.

是否存在任何回调或变通办法,以便在将某些事物包括在内时通知"Foobar"课程?

小演示演示:

# 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
Run Code Online (Sandbox Code Playgroud)

这就是结果:

InstanceMethod: 'visible' added to 'Foobar'
invisible: true
visible: true
wont_exist: false
Run Code Online (Sandbox Code Playgroud)

附加信息:

我真的需要使用像method_added这样的钩子.

ActiveModel通过匿名模块在运行时将class_instance_methods添加到Class.

Ale*_*ohl 8

问题是包含模块不会向类添加方法 - 它只会更改方法调用链.此链定义将搜索哪个类/模块的方法,该方法未针对相关类定义.包含模块时会发生什么是在该链中添加一个条目.

这与在超类中添加方法时完全相同 - 这不会调用,method_added因为它没有在超类中定义.如果子类可以改变超类的行为,那将是非常奇怪的.

您可以通过重新定义include您的类来手动调用为包含的模块添加的方法来解决此问题:

class Foobar
  def self.include(included_module)
    included_module.instance_methods.each{|m| self.method_added(m)}
    super
  end
end
Run Code Online (Sandbox Code Playgroud)

它比重新定义included方法更安全Module- 变化仅限于您自己定义的类.