How to find where a method is defined at runtime? How to find where a method is defined at runtime? ruby ruby

How to find where a method is defined at runtime?


This is really late, but here's how you can find where a method is defined:

http://gist.github.com/76951

# How to find out where a method comes from.# Learned this from Dave Thomas while teaching Advanced Ruby Studio# Makes the case for separating method definitions into# modules, especially when enhancing built-in classes.module Perpetrator  def crime  endendclass Fixnum  include Perpetratorendp 2.method(:crime) # The "2" here is an instance of Fixnum.#<Method: Fixnum(Perpetrator)#crime>

If you're on Ruby 1.9+, you can use source_location

require 'csv'p CSV.new('string').method(:flock)# => #<Method: CSV#flock>CSV.new('string').method(:flock).source_location# => ["/path/to/ruby/1.9.2-p290/lib/ruby/1.9.1/forwardable.rb", 180]

Note that this won't work on everything, like native compiled code. The Method class has some neat functions, too, like Method#owner which returns the file where the method is defined.

EDIT: Also see the __file__ and __line__ and notes for REE in the other answer, they're handy too. -- wg


You can actually go a bit further than the solution above. For Ruby 1.8 Enterprise Edition, there is the __file__ and __line__ methods on Method instances:

require 'rubygems'require 'activesupport'm = 2.days.method(:ago)# => #<Method: Fixnum(ActiveSupport::CoreExtensions::Numeric::Time)#ago>m.__file__# => "/Users/james/.rvm/gems/ree-1.8.7-2010.01/gems/activesupport-2.3.8/lib/active_support/core_ext/numeric/time.rb"m.__line__# => 64

For Ruby 1.9 and beyond, there is source_location (thanks Jonathan!):

require 'active_support/all'm = 2.days.method(:ago)# => #<Method: Fixnum(Numeric)#ago>    # comes from the Numeric modulem.source_location   # show file and line# => ["/var/lib/gems/1.9.1/gems/activesupport-3.0.6/.../numeric/time.rb", 63]


I'm coming late to this thread, and am surprised that nobody mentioned Method#owner.

class A; def hello; puts "hello"; end endclass B < A; endb = B.newb.method(:hello).owner=> A