你如何处理参数&在Ruby中动态定义方法时阻塞?

时间:2011-12-14 22:17:39

标签: ruby metaprogramming

下面是可以动态地将日志记录添加到方法的类的代码。这适用于方法不带参数且不接受任何阻塞的情况。

如何重写代码,以便即使接受参数并接受块也可以添加方法的日志记录?

class X
    def greet
        puts "hi"
    end

    def self.add_logging(method_name)
        alias_method("original_#{method_name}".to_sym, method_name) 

        #How do i rewrie this to account for method_name's arguments and ability to accept a block?
        define_method(method_name) do
            puts "calling #{method_name}"
            send "original_#{method_name}".to_sym
            puts "done #{method_name}"
        end
    end
end

x = X.new
x.greet
X.add_logging(:greet)
x.greet

输出

>hi 
>calling greet 
>hi 
>done greet

2 个答案:

答案 0 :(得分:3)

class X
  def self.add_logging method
    alias_method "original_#{method}", method
    define_method(method) do |*args, &pr|
      puts "calling #{method}"
      send "original_#{method}", *args, &pr
      puts "done #{method}"
    end
  end
  def greet person
    puts "hi #{person}"
  end
end

x = X.new
x.greet("Joe")
X.add_logging(:greet)
x.greet("Jane")

会给:

hi Joe
calling greet
hi Jane
done greet

答案 1 :(得分:2)

据我所知define_method - 方法块接受参数,这些参数代表方法参数,所以我建议如下:

define_method(method_name) do |*arguments|
        puts "calling #{method_name}"
        send "original_#{method_name}".to_sym, *arguments
        puts "done #{method_name}"
end
块中的do-part中的

*arguments包含在将方法method_name调用到数组时发送的所有参数/参数,并且send-method调用中的*arguments扩展它们再次用于原始方法。