37

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.

7
  • 4
    Could you accept answers to your previous questions? Commented Mar 26, 2012 at 8:21
  • 4
    @Arsen7 Oh thank you very much for reminding me. I am quite new to this community. I have accepted them now. Commented Mar 26, 2012 at 9:21
  • That's nice. :-) And how about grep? Or you, actually, meant that this was what I have reminded You of? ;-) Commented Mar 26, 2012 at 11:27
  • @Arsen7 Hahaha Not at all do I find any selfishness:) god I am beginning to love this community. Commented Mar 28, 2012 at 4:07
  • Yeah, grep is fine if you at least know the possible scope and the scope is small. Sometimes the main project relies on too many dependencies and constants are defined outside somewhere else. Commented Mar 28, 2012 at 4:10

6 Answers 6

23

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 
Sign up to request clarification or add additional context in comments.

3 Comments

one more useful snippet: Object.const_source_location('Admin::LIMIT')
@itsnikolay thank you! This went directly in my dotfiles: github.com/BuonOmo/dotfiles/blob/…. Basically adding a method like IRB::Color.csl # => /path/to/irb/color.rb:X
@UlysseBN I like it! Let me add it to my answer :beer:
20

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

2 Comments

This is a great suggestion!
Great answer. I found underscore wasn't available for me in String on Ruby 2.4.2. I got by with downcase, but if your class name is multiple words, you'd need to turn it to snake case somehow.
8

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

1 Comment

Consider ripgrep rather than ack, it is way faster! ag is also a good alternative.
5

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 => "" 

3 Comments

wow, never would have thought of that, this works for Modules and Classes too, awesome!
also I found this gem for Class and Class methods, maybe it helps someone too github.com/daveallie/where_is
This is great since the project I'm working on is not quite yet on Ruby 2.7. Thank you!
4

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.

Comments

2

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

1 Comment

It doesn't look like there's a way to find the source location from this, though.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.