Minqi Pan
Minqi Pan

Reputation: 2801

How do I find where a constant is defined in Ruby?

Using pry, it's very simple to find where a method is defined and see the source by edit-method command. Yet there is no correspondence for class itself. When that class has no methods defined itself, it's hard to locate the source through pry.

Classes are constants, so it's equivalent to ask where to find the source in which a particular Ruby constant is defined. Thank you very much.

Upvotes: 37

Views: 10507

Answers (6)

Chris Salzberg
Chris Salzberg

Reputation: 27374

There is a better way to do this as of Ruby 2.7, which is Module.const_source_location.

> Admin.const_source_location(:LIMIT)
#=> ["SOME_PATH/user.rb", 2]

References:

Bonus from @ulysse-bn:

To have a quick access to this method, you can add it to IRB config like this:

  • ~/.irbrc
# displays path of constant
#
# Usage:
#
#     _source_location(::ActiveRecord::Base)
#
def _source_location(const)
  Object.const_source_location(const.name)
end

Upvotes: 23

Ulysse BN
Ulysse BN

Reputation: 11396

A hacky way for debugging purposes: start a console (for instance with binding.irb) and redefine the constant. You'll get an error message with the previous definition path!

> Foo = ""
(irb):11: warning: already initialized constant Foo
/path/to/foo.rb:1: warning: previous definition of Foo was here
=> ""

Upvotes: 5

Alex
Alex

Reputation: 2518

In ruby, $"holds all the file names that are loaded via Kernel.load. So you could try something like this:

constant = User
$".detect{|load_path|
  load_path.include?(constant.to_s.underscore)
}

Note: The method underscore is part of Rails/ActiveSupport

Upvotes: 20

Schneems
Schneems

Reputation: 15828

If the constant you're looking for has methods (is a class or module) you can use the Method class to find out where it is defined.

class Foo
  def bar
  end

  def self.baz
  end
end

Foo.instance_method(:bar).source_location
Foo.method(:baz).source_location

A bit of a hack and doesn't help with pure constants class Foo; BAHZ = 2; end but it is better than nothing.

Upvotes: 4

horseyguy
horseyguy

Reputation: 29895

Use ack, sometimes if I reach the limits of Pry (and Ruby) i resort to using it. Great thing about it is you can invoke it from within Pry itself using its shell integration features, usually just typing .ack ClassName does the trick, however it requires that the class is defined in a file under the current directory.

In the case that the class is not defined in the current directory, then you can always resort to look up one of its methods, take the source location from there, and then use Pry's cat command to display it (with syntax highlighting) or Pry's edit command to jump directly to its definition.

The case where a class does NOT have any instance methods defined is fairly rare -- and such a class is usually quite uninteresting anyway :)

EDIT:

The most recent version of Pry (0.9.9) can now show the source for modules/classes using the normal show-source command. It requires that the module/class has at least one defined method however

Upvotes: 8

ScottJShea
ScottJShea

Reputation: 7111

Well you could try Module.constants(true) as stated here It might take a bit more than using pry offers but it would allow you a chance to peek into the Modules involved

Upvotes: 2

Related Questions