Ora

How to Locate Where a Method is Defined in Ruby

Published in Ruby Method Introspection 6 mins read

To pinpoint the exact file and line number where a method is defined in Ruby, you primarily utilize two powerful tools: the source_location method available on a Method object and the show_source command within IRB. While ls in IRB can display information about an object and its methods, it does not reveal the method's source file location.

Ruby provides robust mechanisms for introspection, allowing developers to delve into the internals of their code and the Ruby standard library. Understanding where a method originates is crucial for debugging, comprehending library behavior, and extending existing functionalities.

Understanding Method Definitions in Ruby

A method in Ruby is a block of code associated with an object or a class that can be called to perform a specific action. When we talk about "where a method is defined," we're referring to the specific source file and line number in that file where the method's implementation resides. This information is invaluable for developers wanting to explore Ruby's core classes, gems, or even their own application's complex method structures.

Primary Methods for Locating Ruby Method Definitions

There are three main ways to investigate method definitions, especially within an interactive Ruby session like IRB:

1. Using Method#source_location

The source_location method, available on Method objects, is the most direct way to find the file and line number of a method's definition. It returns an array containing the file path as the first element and the line number as the second.

How it works:

  1. Obtain a Method object for the method you're interested in. You can do this using Object#method or Object#instance_method.
  2. Call .source_location on the resulting Method object.

Example:

# For an instance method (e.g., `String#upcase`)
method_object = String.instance_method(:upcase)
puts method_object.source_location
# => ["/path/to/ruby/2.x.x/string.c", 823] (or similar, depending on Ruby version and implementation)

# For a class method (e.g., `File.read`)
method_object = File.method(:read)
puts method_object.source_location
# => ["/path/to/ruby/2.x.x/file.rb", 1234] (or similar)

# For a method defined in your own code
class MyClass
  def my_custom_method
    "Hello"
  end
end

my_instance_method = MyClass.instance_method(:my_custom_method)
puts my_instance_method.source_location
# => ["/path/to/your/script.rb", 3] (or similar, pointing to the line where it's defined)

Key Advantages:

  • Provides the exact file and line number.
  • Works programmatically, allowing integration into tools or scripts.
  • Reliable for most Ruby-defined methods.

Limitations:

  • Returns nil for methods defined in C (native extensions) if their source isn't exposed or for methods that are dynamically generated and not associated with a file.
  • Requires obtaining a Method object first.

For more details, refer to the Ruby-doc for Method#source_location.

2. Utilizing IRB's show_source Command

When working interactively in IRB (Interactive Ruby), the show_source command is an incredibly convenient way to display a method's source code directly in your console, including its definition location.

How it works:

  1. Start an IRB session.
  2. Type show_source followed by the method call or reference.

Example:

# Start IRB
$ irb

# Inside IRB:
irb(main):001:0> show_source String.instance_method(:upcase)
# From: string.c (C method)
# Owner: String
# Visibility: public
# Alias of: upcase

irb(main):002:0> show_source File.method(:read)
# From: /path/to/ruby/2.x.x/file.rb @ line 1234
# Owner: File
# Visibility: public
def read(...)
  # ... source code here ...
end

Key Advantages:

  • Extremely user-friendly and quick for interactive exploration.
  • Displays the actual source code along with the location, if available.
  • Handles both instance and class methods easily.

Limitations:

  • Only available within IRB (or Pry, which offers similar functionality).
  • Like source_location, it cannot show the C source for methods implemented in C.

3. Inspecting Objects with ls in IRB (with caveats)

The ls command in IRB is useful for listing methods and constants associated with an object or class. It helps discover what methods are available, but it does not provide the source file or line number for method definitions.

How it works:

  1. Start an IRB session.
  2. Type ls followed by the object or class name.

Example:

# Start IRB
$ irb

# Inside IRB:
irb(main):001:0> ls String
# String.methods:
#   []        allocate  new  try_convert
#
# String#methods:
#   %        *       +       ...   upcase  ...

Key Advantages:

  • Excellent for discovering available methods on an object or class.
  • Quick overview of an object's API surface.

Limitations:

  • Crucially, it does not display the source location or the source code of the methods. Its purpose is method discovery, not definition lookup.
  • Less granular control compared to source_location.

When to Use Each Approach

Choosing the right method depends on your context and what information you need:

Method Purpose Best Used For Output Detail
Method#source_location Programmatically finding file and line Scripting, automated checks, integrating into custom tools File path and line number (or nil for C methods)
IRB's show_source command Interactive source code and location lookup Ad-hoc debugging, exploring library code during development Source code, file path, and line number (or "C method" for C)
IRB's ls command Discovering available methods Exploring an object's API, quickly seeing what methods are defined List of method names (does NOT include source location)

Practical Considerations

  • C-Defined Methods: Many core Ruby methods (like String#upcase, Array#push) are implemented in C for performance reasons. For these methods, source_location will return nil, and show_source will indicate "C method" because their source is not a .rb file. To view their source, you would need to examine the Ruby source code on GitHub.
  • Dynamically Defined Methods: Methods created at runtime using define_method or module_eval/class_eval may or may not have an associated source_location depending on how they are defined and if a block with a source location is provided.
  • Gem Exploration: These tools are invaluable when exploring methods defined within Ruby gems. You can quickly jump to the source code of a gem's method to understand its implementation details.

By mastering these introspection techniques, Ruby developers gain a deeper understanding of their applications and the underlying Ruby ecosystem.