Get class location from class object
For Methods
and Procs
Ruby 1.9 has method called source_location:
Returns the Ruby source filename and line number containing this method or nil if this method was not defined in Ruby (i.e. native)
So you can request for the method:
m = Foo::Bar.method(:create)
And then ask for the source_location
of that method:
m.source_location
This will return an array with filename and line number.
E.g for ActiveRecord::Base#validates
this returns:
ActiveRecord::Base.method(:validates).source_location
# => ["/Users/laas/.rvm/gems/ruby-1.9.2-p0@arveaurik/gems/activemodel-3.2.2/lib/active_model/validations/validates.rb", 81]
For classes and modules, Ruby does not offer built in support, but there is an excellent Gist out there that builds upon source_location
to return file for a given method or first file for a class if no method was specified:
- ruby where_is module
EDIT: For Ruby 1.8.7 there is a gem that backports source_location
:
- ruby18_source_location
FYI, In Rails's console or debugging sessions of Rails apps, you can find out the disk-location of the file where that particular class is defined. like
> show-source Job
this will give you
From: /home/john/projects/iisifix/app/models/job.rb @ line 13:
Class name: Job
Number of monkeypatches: 6. Use the `-a` option to display all available monkeypatches
Number of lines: 66
class Job < ApplicationRecord
belongs_to :quote_request
belongs_to :garage
Here's a simple example showing how I track locations in code. If I need to know a location in a module:
class Foo
attr_reader :initialize_loc
def initialize
@initialize_loc = [__FILE__, __LINE__]
# do more stuff...
end
end
If I need to know where something happened:
require_relative 't1'
foo = Foo.new
# do lots of stuff until you want to know where something was initialized.
puts 'foo initialized at %s:%s' % foo.initialize_loc
When I run the code I get:
FooBar:Desktop foobar ruby t2.rb
foo initilized at /Users/foobar/Desktop/t1.rb:4
If I don't want to mess with the source-code of the module, and want the debugger to jump in when I need it, I'll have the debugger do just that:
require_relative 't1'
require 'ruby-debug'
debugger
foo = Foo.new
# do lots of stuff until you want to know where something was initilized.
puts 'foo initilized at %s:%s' % foo.initialize_loc
The execution will stop and I'll drop into the debugger at the line immediately following debugger
:
[0, 9] in t2.rb
1 require_relative 't1'
2 require 'ruby-debug'
3
4 debugger
=> 5 foo = Foo.new
6 # do lots of stuff until you want to know where something was initilized.
7 puts 'foo initilized at %s:%s' % foo.initialize_loc
8
t2.rb:5
foo = Foo.new
(rdb:1)
A simple s
will "step" me into the next line of code, which will be in the initialize
block for Foo
:
(rdb:1) s
[-1, 8] in /Users/foobar/Desktop/t1.rb
1 class Foo
2 attr_reader :initialize_loc
3 def initialize
=> 4 @initialize_loc = [__FILE__, __LINE__]
5 # do more stuff...
6 end
7 end
8
/Users/foobar/Desktop/t1.rb:4
@initialize_loc = [__FILE__, __LINE__]
(rdb:1)
Beyond this, using tools like grep -rn target_to_find path_to_search
to recursively search directories and list the filename and line numbers of lines matching the target, will go a long ways to helping find what you're looking for.
Or, using :vim /target_to_find/ path_to_search
from inside Vim will return the files you're looking for.