Ruby でソースコード定義元を追う

Method#source_location (Ruby 3.0.0 リファレンスマニュアル)

# ------- /tmp/foo.rb ---------
class Foo
  def foo; end
end
# ----- end of /tmp/foo.rb ----

require '/tmp/foo'

m = Foo.new.method(:foo) # => #<Method: Foo#foo>
m.source_location # => ["/tmp/foo.rb", 2]

method(:puts).source_location # => nil

Module#const_source_location (Ruby 3.0.0 リファレンスマニュアル)

# test.rb:
class A         # line 1
  C1 = 1
  C2 = 2
end

module M        # line 6
  C3 = 3
end

class B < A     # line 10
  include M
  C4 = 4
end

class A # 継続して A を定義する
  C2 = 8 # 定数を再定義する
end

p B.const_source_location('C4')           # => ["test.rb", 12]
p B.const_source_location('C3')           # => ["test.rb", 7]
p B.const_source_location('C1')           # => ["test.rb", 2]

p B.const_source_location('C3', false)    # => nil  -- include したモジュールは検索しない

p A.const_source_location('C2')           # => ["test.rb", 16] -- 最後に定義された位置を返す

p Object.const_source_location('B')       # => ["test.rb", 10] -- Object はトップレベルの定数を検索する
p Object.const_source_location('A')       # => ["test.rb", 1] -- クラスが再定義された場合は最初の定義位置を返す

Object はトップレベルの定数を検索する というのが肝。

see also. Ruby 2.7 adds Module#const_source_location | Saeloun Blog

irb show_source

source: https://github.com/ruby/ruby/blob/af74cc7504efa4d7fa5a0889e4ba97eade68abf1/lib/irb/cmd/show_source.rb#L27-L35

pry の show-source よりは使い勝手がやや悪いのだけど、show_source でソースコードをirbで見れる。

> require 'json'
=> true

> show_source "JSON.parse"

From: /Users/toshimaru.enomoto/.rbenv/versions/3.0.2/lib/ruby/3.0.0/json/common.rb:215

  def parse(source, opts = {})
    Parser.new(source, **(opts||{})).parse
  end

=> nil

see also. Pryはもう古い、時代はIRB - k0kubun’s blog