Как получить список используемых методов в Ruby? - PullRequest
0 голосов
/ 03 мая 2019

эй, я хочу, чтобы мой метод logify помещал каждый метод со своими параметрами и возвращаемым значением моего класса A. Я написал, например, простой класс A с двумя методами add и sub, и результат должен выглядеть следующим образом:

Output:
Method add(1, 2) called 
return value 3
Method sub(1, 2) called
return value -1

Я знаю, что могу получить каждый метод с помощью self.instance_methods(false), но может ли кто-нибудь помочь мне в дальнейшем?

require_relative "log"

class A
    extend Log

    def add(a, b)
      a + b
    end

    def sub(a, b)
      a - b
    end
    logify
  end

    a = A.new
    a.add(2,1)
    a.sub(2,1)
module Log 
   def logify 
   puts self.instance_methods(false)
   end
end

Ответы [ 2 ]

5 голосов
/ 03 мая 2019

Вы можете использовать Module#prepend и Module#prepended, чтобы помочь с этим следующим образом:

module Log 
  def self.prepended(base)
    base.instance_methods(false).each do |m|
      define_method(m) do |*args, &block| 
        puts "Method #{m}(#{args.join(',')}) called"
        val = super(*args, &block)
        puts "return value #{val}"
        val
      end
    end
  end
end

class A
  def add(a, b)
    a + b
  end

  def sub(a, b)
    a - b
  end
end

A.prepend(Log)

Что он делает, так это определяет метод в предварительно добавленном модуле с тем же именем, что и у оригинала, затем строит выходные данные и выполняет исходный метод в середине (super) для получения возвращаемого значения.

Примеры

a = A.new
a.add(2,1)
# Method add(2,1) called
# return value 3
#=> 3
a.sub(2,1)
# Method sub(2,1) called
# return value 1
#=> 1

Предупреждение: это будет показывать только предоставленные аргументы и не будет выводить аргументы по умолчанию в сигнатуре метода

2 голосов
/ 03 мая 2019

Библиотека ядра ruby ​​включает в себя класс TracePoint, который можно использовать для отслеживания практически чего угодно - от определяемых или вызываемых методов или вызываемых исключений, ...

Вот пример использования, который выполнит желаемое отслеживание:

class A
  def add(a, b)
    a + b
  end

  def sub(a, b)
    a - b
  end
end

TracePoint.trace(:call, :return) do |tp|
  next unless tp.defined_class == A
  case tp.event
  when :call
    params = tp.parameters.map { |arg| eval(arg[1].to_s, tp.binding) }
    puts "Method #{tp.method_id}(#{params.join(', ')}) called"
  when :return
    puts "return value #{tp.return_value}"
  end
end

# The trace has been enabled! Any time one of those events occurs, the block is evaluated.
a = A.new
a.add(2,1)
a.sub(2,1)

Вывод:

Метод add (2, 1) называется

возвращаемое значение 3

Метод sub (2, 1) называется

возвращаемое значение 1

Получение данных params, как вы можете видеть, немногохлопотно.TracePoint имеет доступ к методу signature , но вам нужно использовать привязку трассировки , чтобы увидеть, с какими значениями она действительно вызывается.

...