Как вы обрабатываете параметры и блоки при динамическом определении метода в Ruby? - PullRequest
1 голос
/ 15 декабря 2011

Ниже приведен код класса, который может динамически добавлять запись в метод.Это работает в случае, когда метод не принимает параметров и не принимает блок.

Как я могу переписать код, чтобы я мог добавить запись метода, даже если он принимает параметры и принимает блок?

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 ]

3 голосов
/ 15 декабря 2011
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
2 голосов
/ 15 декабря 2011

Насколько мне известно, блок define_method -методов принимает параметры, которые представляют параметры метода, поэтому я бы предложил следующее:

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

*arguments в do-part вБлок оборачивает все аргументы / параметры, которые отправляются при вызове метода method_name, в массив, а *arguments в вызове метода send снова расширяет их для использования в исходном методе.

...