ruby-on-rails - Ruby method_added 回调不触发包括模块

标签 ruby-on-rails ruby callback

我想写一点“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/

相关文章:

ruby-on-rails - Ruby Rails 在返回多个对象的查询中平均两个属性

html - Rails Backbone Marionette Assets 在更改时不再更新?

ruby-on-rails - 检测设计 session 何时过期

mysql - MYSQL 值数组的位置

ruby-on-rails - 为什么将实例变量用于带有 View 的 "connect" Controller ?

ruby - 处理文件列表以格式化 web 文件名(简单)

ruby-on-rails - 如何设置所有 Rails 事务的隔离级别

javascript - 如何将事件传递给 setState 回调函数?

javascript - 回调函数没有被调用

jquery - 回调内绑定(bind)/取消绑定(bind)