Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Rails: メソッド検索をsource_locationとbundle openで行う(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

Rails: メソッド検索をsource_locationとbundle openで行う(翻訳)

Rubyは動的言語なので、すぐに使える多くの優秀なデバッグ機能やイントロスペクション(=オブジェクトを調べる)機能がRubyに備わっていることは重要です。

デバッグやコードの理解を効率的に進めるには、メソッドやコードブロックの定義場所を正確に見つけて前後のソースコードを読み取る機能が欠かせません。Rubyが提供するsource_locationメソッドは、特定のメソッドやブロックが定義されているファイルと行番号を取得できる強力なツールとなります。

🔗 Railsでメソッド定義の場所を調べる方法

以下のように#source_locationメソッドを使って場所を調べます。

"Cars".method(:singularize).source_location
#=> ["/.../activesupport-7.0.8/lib/active_support/core_ext/string/inflections.rb", 60]

次にシェルで以下のコマンドを実行して、そのgemのソースコードを自分のエディタで開きます。

bundle open activesupport

🔗 そうする理由

source_locationは、初めて扱うアプリケーションを調べる場合や、自分のよく知らないコードを調べる場合、あるいは自分が使っている機能がどのgemにあるかを調べる場合にとても有用です。

ソースコードを読むことは良い学習方法のひとつです。特に、Rails自身やさまざまなgemのようにバトルテストを経たコードを読むことは大きな学びがあります。

Railsフレームワーク作者たちのおかげで、Railsの「魔法のような」メタプログラミングを駆使したメソッドでもsource_locationで調べられます。Active Recordのclass_evalで生成されるさまざまな関連付けメソッドは、特殊な構文を渡すことでsource_locationが引き続き使えるようになっています。もしそうなっていなければ、source_locationを呼び出しても常に(eval)が最初の結果として表示されてしまうでしょう。

class Car < ApplicationRecord
  has_many :seats

  # ...
end

Car.first.method(:seats).source_location
#=> [".../activerecord-7.0.8/lib/active_record/associations/builder/association.rb", 103]

上に続いて、以下のコマンドラインで該当箇所を開きます。

bundle open activerecord

🔗 そうしない理由があるとすれば

source_locationでいろいろ実験していると、必ずしも有用な結果が得られない場合もあることに気づくかもしれません。Ruby「コア」に含まれるメソッドの多くはC言語で実装されていますが、これらのメソッド定義にはRubyコードから直接アクセスできません。そのため、そうしたコアメソッドに対してsource_locationを呼び出すとたいていnilが返されます。

"Cars".method(:upcase).source_location
#=> nil

C拡張(RubyコードからCを呼び出す機能)を利用するメソッドの場合もsource_locationを利用できません。source_locationが利用できるのは、ソースコードがRubyで書かれているgemで定義されたメソッドに対してのみです。

source_locationは開発中やデバッグ中は非常に有用ですが、誤ってproductionコードに入れないようご注意ください。

関連記事

Rails: number_to_humanメソッドの書式をカスタマイズするときのコツ(翻訳)

Ruby: 数値の正負チェックはpositive?やnegative?で明確に書こう(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。