简体   繁体   中英

How to get a list of used methods in Ruby?

hey I want that my method logify puts each method with its parameters and return value of my class A. I wrote for example a simple class A with two methods add and sub and the output should look like that:

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

I know that I can get each method with self.instance_methods(false) but can someone please help me further?

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

You can use Module#prepend and Module#prepended to help with this like so:

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)

What this does is it defines a method in the prepended module with the same name as the original then builds your output and delagets to the original method in the middle ( super ) to obtain the return value.

Examples

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

Caveat: this will only show the provided arguments and will not output default arguments in the method signature

The ruby core library includes the class TracePoint , which can be used to trace just about anything - from methods being defined, or invoked, or exceptions being raised, ...

Here is an example usage, which will perform the tracking you desired:

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)

Output:

Method add(2, 1) called

return value 3

Method sub(2, 1) called

return value 1

Fetching the params data is, as you can see, a little troublesome. TracePoint has access to the method signature , but you need to make use of the trace's binding to see what values it's actually been called with.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM