1. ホーム
  2. ruby-on-rails

[解決済み] 実行時にメソッドが定義されている場所を見つけるには?

2022-03-16 08:25:31

質問

最近、一連のコミットが行われた後、バックエンドプロセスの実行に失敗する問題が発生しました。そこで、私たちはいい子にしていて、バックエンドプロセスを実行するために rake test しかし、Railsのライブラリ読み込みに奇妙な点があったため、本番モードでMongrelから直接実行したときのみ、この現象が発生しました。

このバグを追跡したところ、新しいRails gemがStringクラスのメソッドを上書きしてしまい、実行時のRailsコードにある狭い範囲での使用を壊してしまったことが原因でした。

とにかく、長い話ですが、実行時に、あるメソッドがどこで定義されているかをRubyに問い合わせる方法はないでしょうか?例えば whereami( :foo ) を返します。 /path/to/some/file.rb line #45 ? この場合、Stringクラスで定義されていると言っても、それはどこかのライブラリでオーバーロードされているため、役に立たないでしょう。

ソースがプロジェクト内に存在することは保証できないので 'def foo' があれば、必ずしも必要なものが得られるとは限りません。 多数 def foo を使用しているため、実行時までどれを使用しているかわからないことがあります。

解決方法は?

本当に今更ですが、あるメソッドがどこで定義されているかを調べる方法を紹介します。

http://gist.github.com/76951

# How to find out where a method comes from.
# Learned this from Dave Thomas while teaching Advanced Ruby Studio
# Makes the case for separating method definitions into
# modules, especially when enhancing built-in classes.
module Perpetrator
  def crime
  end
end

class Fixnum
  include Perpetrator
end

p 2.method(:crime) # The "2" here is an instance of Fixnum.
#<Method: Fixnum(Perpetrator)#crime>

Ruby 1.9以上なら source_location

require 'csv'

p CSV.new('string').method(:flock)
# => #<Method: CSV#flock>

CSV.new('string').method(:flock).source_location
# => ["/path/to/ruby/1.9.2-p290/lib/ruby/1.9.1/forwardable.rb", 180]

この方法は、ネイティブコンパイルされたコードのように、すべてにおいてうまくいくわけではないことに注意してください。また メソッドクラス のような巧妙な関数もあります。 メソッド#オーナ これは、そのメソッドが定義されているファイルを返すものです。

EDIT: また __file____line__ や、別解のREEの注意書きも便利ですよ。-- wg