2013-07-18 50 views
0

我想所有的包装类方法用于记录一个模块,像这样:如何有一个重新定义其他类方法的类方法?

module SomeModule 

    def self.foo 
    puts "bar" 
    end 

    class << self 
    SomeModule.methods(false).each do |method| 
     alias_method "old_#{method}".to_sym, method 
     define_method method do |*args| 
     puts "Called method: #{method}" 
     send "old_#{method}", *args 
     end 
    end 
    end 
end 

SomeModule.foo 
#-> Called method: foo 
#-> bar 

完美的作品。但是,如果我想只在我调用方法时才会发生包装,该怎么办?我如何才能让当你调用

module SomeModule 
    def self.foo 
    puts "bar" 
    end 

    def self.add_logging_to_all_methods 
    #??? 
    end 
end 
SomeModule.add_logging_to_all_methods 

SomeModule.foo 
#-> Called method: foo 
#-> bar 
+0

哦,其实我确实有这方面的工作还行......原来,我的问题是别的地方......它似乎总是这样... –

回答

1

我不会问你要这个东西,但在这里它是:

module SomeModule 

    def self.foo 
    puts "bar" 
    end 

    def self.add_logging_to_all_methods 
    eigenclass = class << self; self; end 
    methods(false).each do |method| 
     eigenclass.class_eval do 
     alias_method "old_#{method}".to_sym, method 
     define_method method do |*args| 
      puts "Called method: #{method}" 
      send "old_#{method}", *args 
     end 
     end 
    end 
    end 
end 
SomeModule.add_logging_to_all_methods 

SomeModule.foo 

注意,这还增加了“记录”到add_logging_to_all_methods,但只调用它后,因此,如果您只调用一次,你不应该看到任何错误。

什么eigenclass意味着您添加此方法fooadd_logging_to_all_methods的“实例”。通过在class << self; end块内返回self,我得到该实例。然后,我要求该块在该实例的上下文中进行评估,该实例与上一个方法或多或少相同。

可能有更简单的方法来做到这一点。

+0

谢谢,这工作很漂亮...在真正的代码中,我实际上是将我想包装的方法进行正规化,因此没有这种危险。 –

0

啊请不要介意,只是放置在方法全班< <自身块的工作好这一点。

1

您可以应用在所有类:

ObjectSpace.each_object.select { |o| o.is_a? Class }.each do |klass| 
    klass.class_eval do 
    methods(false).each do |method| 
     alias_method "old_#{method}".to_sym, method 
     define_method method do |*args| 
     puts "Called method: #{method}" 
     send "old_#{method}", *args 
     end 
    end 
    end rescue nil 
end 
相关问题