2017-05-07 19 views
-1

我想在任何時候在Rails應用程序中重新定義方法時打印類和方法,即使它發生在包含的gem中。我知道有一個名爲method_added的鉤子,在重新定義方法時被調用,但我不知道如何使用它來捕獲任何被重新定義的東西。如何隨時登錄任何方法在Rails中修補猴子

我該如何使用method_added

我已將此添加的boot.rb:

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

不過,這似乎是在捕捉每一個類的每一個方法?

+3

請定義*精確*你的意思是「猴子修補」。另外,'method_added'鉤子如何不能滿足您的要求? –

+0

'method_added'聽起來像滿足我的要求。我不知道如何使用它。這是我的問題。通過「猴子修補」我的意思是重新定義。就像'Foo'類中的'x'和其他一些代碼一樣,可能在另一個gem中重新定義'x'方法。 – marathon

回答

5

可以使用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鉤被執行是不完全指定;在之後,可能會執行該方法已被定義,這意味着該檢查將始終爲真。 (至少這就是我的測試中發生的情況。)