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
end
end
class Fixnum
include Perpetrator
end
p 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
How do I find where a ruby method is declared?
When I need to find where a method is declared on some class, say 'Model', I do
Model.ancestors.find {|c| c.instance_methods(false).include? :deactivate! }
This searches the ancestor tree in the same order that ruby does for the first that has the method in instance_methods(false)
, which only includes non-inherited methods.
Note: before ruby 1.9, the methods were listed as strings not symbols, so it would be
Model.ancestors.find {|c| c.instance_methods(false).include?('deactivate!') }
Finding out where methods are defined in Ruby/Rails (as opposed to Java)
The Pry gem is designed precisely for this kind of explorative use-case.
Pry is an interactive shell that lets you navigate your way around a program's source-code using shell-like commands such as cd
and ls
.
You can pull the documentation for any method you encounter and even view the source code, including the native C code in some cases (with the pry-doc
plugin). You can even jump directly to the file/line where a particular method is defined with the edit-method
command. The show-method
and show-doc
commands also display the precise location of the method they're acting on.
Watch the railscast screencast for more information.
Here are some examples below:
pry(main)> show-doc OpenStruct#initialize
From: /Users/john/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/ostruct.rb @ line 46:
Number of lines: 11
visibility: private
signature: initialize(hash=?)
Create a new OpenStruct object. The optional hash, if given, will
generate attributes and values. For example.
require 'ostruct'
hash = { "country" => "Australia", :population => 20_000_000 }
data = OpenStruct.new(hash)
p data # -> <OpenStruct country="Australia" population=20000000>
By default, the resulting OpenStruct object will have no attributes.
pry(main)>
You can also look up sourcecode with the show-method
command:
pry(main)> show-method OpenStruct#initialize
From: /Users/john/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/ostruct.rb @ line 46:
Number of lines: 9
def initialize(hash=nil)
@table = {}
if hash
for k,v in hash
@table[k.to_sym] = v
new_ostruct_member(k)
end
end
end
pry(main)>
See http://pry.github.com for more information :)
checking if a method is defined on the class
Use this:
C.instance_methods(false).include?(:a)
C.instance_methods(false).include?(:b)
C.instance_methods(false).include?(:c)
The method instance_methods
return an Array of methods that an instance of this class would have. Passing false
as first parameter returns only methods of this class, not methods of super classes.
So C.instance_methods(false)
returns the list of methods defined by C
.
Then you just have to check if that method is in the returned Array (this is what the include?
calls do).
See docs
Ruby - determining method origins?
Object#method
returns a Method
object giving meta-data about a given method. For example:
> [].method(:length).inspect
=> "#<Method: Array#length>"
> [].method(:max).inspect
=> "#<Method: Array(Enumerable)#max>"
In Ruby 1.8.7 and later, you can use Method#owner
to determine the class or module that defined the method.
To get a list of all the methods with the name of the class or module where they are defined you could do something like the following:
obj.methods.collect {|m| "#{m} defined by #{obj.method(m).owner}"}
Source location of a class
[not actually an answer to your problem, but too long for a comment]
source_location
doesn't seem to help here, because dynamic methods can be created with an arbitrary location:
# my_class.rb
class MyClass
attr_accessor :foo
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
def bar
end
RUBY
class_eval(<<-RUBY, 'dummy.rb', 42)
def baz
end
RUBY
end
p MyClass.instance_method(:foo).source_location
p MyClass.instance_method(:bar).source_location
p MyClass.instance_method(:baz).source_location
Output:
$ ruby my_class.rb
["my_class.rb", 4]
["my_class.rb", 7]
["dummy.rb", 42]
Related Topics
Ruby/Rails Image Processing Libraries
Accepts_Nested_Attributes_For Rails 4 Is Not Deleting
Why Was the Object_Id for True and Nil Changed in Ruby2.0
How Does Pack() and Unpack() Work in Ruby
Ruby $Stdin.Gets Without Showing Chars on Screen
Cannot Load Such File - Rubygems.Rb
Rspec and Shoulda - Complementary or Alternatives
Differencebetween Ruby's Send and Public_Send Methods
How to Do Attr_Accessor_With_Default in Ruby
Why I Can Not Call Super in Define_Method with Overloading Method
How to Handle Multiple Models in One Rails Form
Using Yield Inside Define_Method in Ruby
Escape Double and Single Backslashes in a String in Ruby
How Does MACports Install Packages? How to Activate a Ruby Installation Done via MACports
Rails Console Not Working on Server
Get the Name of a Local Variable
How to Assert Certain Method Is Called with Ruby Minitest Framework