/ #ruby #rails 

メソッドが定義された場所を調べる

rubyでは、あるオブジェクトが持つメソッドのソースがどこにあるのかは、自明ではなかったりします。

includeだのprependだのが使われていると追いにくかったり、、

pryを使う場合: show-methodを使う

使い方: rails cした後に show-method [メソッド名] と入力します。

[/Users/cesario/go/src/github.com/hoshinotsuyoshi/s3_explorer]$ bin/rails c
Running via Spring preloader in process 41502
Loading development environment (Rails 5.0.1)
[1] pry(main)> show-method ''.to_json

From: /Users/cesario/go/src/github.com/hoshinotsuyoshi/s3_explorer/vendor/bundle/ruby/2.4.0/gems/activesupport-5.0.1/lib/active_support/core_ext/object/json.rb @line 31:
Owner: ActiveSupport::ToJsonWithActiveSupportEncoder
Visibility: public
Number of lines: 9

def to_json(options = nil)
  if options.is_a?(::JSON::State)
    # Called from JSON.{generate,dump}, forward it to JSON gem's to_json
    super(options)
  else
    # to_json is being invoked directly, use ActiveSupport's encoder
    ActiveSupport::JSON.encode(self, options)
  end
end

おすすめです。

pryを使う場合: RubyのCoreで実装されたメソッドも。

RubyのCoreで実装されたメソッドの場合は、

[1] pry(main)> show-method [].select
Error: Cannot locate this method: select. Try `gem-install pry-doc` to get access to Ruby Core documentation.

とエラーになってしまうので、pry-doc gemを入れます。

Gemfileにpry-docを追加して利用します。

追加した後に実行するとCのコードが吐かれる。

[1] pry(main)> show-method [].select

From: array.c (C Method):
Owner: Array
Visibility: public
Number of lines: 15

static VALUE
rb_ary_select(VALUE ary)
{
    VALUE result;
    long i;

    RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    result = rb_ary_new2(RARRAY_LEN(ary));
    for (i = 0; i < RARRAY_LEN(ary); i++) {
        if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
            rb_ary_push(result, rb_ary_elt(ary, i));
        }
    }
    return result;
}

pryを使わない場合: Method#source_locationを使う

rubyにはメソッドをオブジェクト化したクラス Method クラスがあります。

.method(:メソッド名)でメソッドが取り出せます。

Methodクラスには source_locationというメソッドがあるので、これで該当ファイル・行数を表示することができます。

[/Users/cesario/go/src/github.com/hoshinotsuyoshi/s3_explorer]$ bin/rails c
Running via Spring preloader in process 43885
Loading development environment (Rails 5.0.1)
[1] pry(main)> ''.method(:to_json)
=> #<Method: String(ActiveSupport::ToJsonWithActiveSupportEncoder)#to_json>
[2] pry(main)> ''.method(:to_json).source_location
=> ["/Users/cesario/go/src/github.com/hoshinotsuyoshi/s3_explorer/vendor/bundle/ruby/2.4.0/gems/activesupport-5.0.1/lib/active_support/core_ext/object/json.rb", 31]

余談ですが、Methodクラスにはおもしろメソッドがいっぱいあって楽しいです。

  • Method#parameters
    • Method オブジェクトの引数の情報を返します。
  • Method#unbind
    • self のレシーバとの関連を取り除いた UnboundMethod オブ ジェクトを生成して返します。
  • Method#super_method
    • super を実行した際に実行されるメソッドを Method オブジェ クトにして返します。
  • Method#arity
    • メソッドが受け付ける引数の数を返します。可変長の場合は負の値が返る。
  • Method#curry
    • self を元にカリー化した Proc を返します。
  • Method#owner
    • このメソッドが定義されている class か module を返します。
  • Method#receiver
    • このメソッドオブジェクトのレシーバを返します。

参考

まとめ

pry全然使いこなせていないので、使っていきたいですね


Author

hoshinotsuyoshi

星野剛志(ほしのつよし) web application engineer. ruby/rails/docker