【问题标题】:How to log any time any method has been monkey patched in Rails如何在 Rails 中对任何方法进行猴子修补时随时记录
【发布时间】:2017-05-07 08:50:10
【问题描述】:

我想在 Rails 应用程序中重新定义方法时打印类和方法,即使它发生在包含的 gem 中。我知道有一个名为method_added 的钩子会在重新定义方法时被回调,但我不知道如何使用它来捕获任何被重新定义的东西。

如何使用method_added

我将此添加到 boot.rb:

class Module
  def method_added(name)
    puts "adding #{self.name.underscore.capitalize}  #{name}\n"
  end
end

但这似乎是捕获每个类中的每个方法?

【问题讨论】:

  • 准确地定义您所说的“猴子补丁”是什么意思。还有,method_added钩子怎么不满足你的要求?
  • method_added 听起来满足我的要求。我不知道如何使用它。那是我的问题。 “猴子补丁”是指重新定义。如Foo 类中有一个方法x 和其他一些代码,可能在另一个gem 中重新定义了方法x

标签: ruby-on-rails ruby monkeypatching


【解决方案1】:

您可以使用Module#method_added 挂钩来记录所有正在定义的方法,并检查您之前是否已经看过相同的方法:

require 'set'

module LoggingMethodAdded
  def method_added(meth)
    @methods ||= Set.new
    puts "Monkey patching #{meth} in #{self}!" if @methods.include?(meth)
    @methods << meth
    super
  end
end

class Module
  prepend LoggingMethodAdded
end

class Foo; def foo; end end

class Foo; def foo; end end
# Monkey patching foo in Foo!

module Bar; def foo; end end

module Bar; def foo; end end
# Monkey patching foo in Bar!

但是,这仅适用于在您加载钩子方法后添加的方法。显而易见的替代方法是检查已经定义的方法,而不是自己记录它们:

def method_added(meth)
  puts "Monkey patching #{meth} in #{self}!" if (instance_methods(false) | private_instance_methods(false)).include?(meth)
  super
end

但这不起作用:它没有准确指定method_added钩子被执行;它可能会在定义方法之后执行,这意味着检查将始终为真。 (至少在我的测试中是这样的。)

【讨论】:

    猜你喜欢
    • 2010-10-01
    • 2021-03-10
    • 1970-01-01
    • 2016-11-27
    • 1970-01-01
    • 2019-08-06
    • 2011-04-19
    • 2017-02-12
    • 2012-12-11
    相关资源
    最近更新 更多