Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a straightforward catchall way to log the methods that are being called on an object in Ruby?

Tags:

ruby

Is there a quick way to track the methods that are being called on an object? Often, when I'm working with a gem at a level just below their public interface, I run into errors that are hard to track down. Ultimately, I end up tracking the object through the source code and keeping everything in my head.

But it would be nice to be able to call something like a #log_method_calls on an object so that, say, all methods called on it get printed to stdout or something. Is there any way to accomplish this?

like image 483
Steven Avatar asked Jun 19 '11 01:06

Steven


1 Answers

There are several methods to do it, depending on the situation.

If it' possible to create a new object instead of the observed, you can easily write an observer class using method_missing.

class LogProxy  
  def initialize obj
    @obj = obj
  end

  def method_missing(name, *args)
    puts "#{name} => #{args.to_s}"  
    @desk.send(name, *args)
  end
end

If it's not possible, you still may use alias_method. It's a bit more tricky, but using Module.instance_methods you can chain every method of anything.

Something like:

module Logger

  def self.included(mod)
    mod.instance_methods.each do |m|
      next if m =~ /with_logging/
      next if m =~ /without_logging/

      mod.class_eval do

        define_method "#{m}_with_logging" do |*args|
          puts "#{m} called #{args.to_s}"
          self.send_without_logging "#{m}_without_logging", *args
        end

        alias_method "#{m}_without_logging", m
        alias_method m, "#{m}_with_logging"
      end

    end
  end

end

TargetClass.send(:include, Logger)
like image 105
Dutow Avatar answered Sep 28 '22 17:09

Dutow