Pry上でRailsアプリのコードを読むために使える知識まとめ

# (2022/06/14 追記) 
この記事を書いた頃（2016年ごろ）はPryでしかできなかったことが、標準のIRBでもできるようになってきています。
ですので、pryを入れる必要はないかもしれません。pryを入れる前に、以下の記事を読んでみると良いと思います。

- [Pryはもう古い、時代はIRB \- k0kubun's blog](https://k0kubun.hatenablog.com/entry/2021/04/02/211455)


____

Ruby on Rails 製のソフトウェアのソースを追う時に、できるだけPryを離れずに疑問を解決したいと思いました。疑問はすべてPry上で解決できるのが理想です。

そこで、Pry上でRailsアプリのコードを読むために使える知識をまとめておくことにしました。

# Pryとは
REPL(Read-Eval-Print-Loop)です。`pry-rails`というgemを使えば、Pry上にそのRails製ソフトウェアの環境が立ち上がります。環境という言い方がいいのかよくわかりませんが、要は外部ライブラリやらモデル、コントローラ、ヘルパ、自作モジュールなど全てのコードを参照できる状態でいろいろいじくくれるということです。

# show-*
なにかを見る系のコマンド。

## show-model
```
[1] pry(main)> show-model User
```

とかするとモデルが持つアトリビュートとかリレーションとかが見れます。

## show-models

モデル一覧。

```
pry(main)> show-models --grep User
```

初めてみるRailsプロジェクトで、ユーザー関係の情報とりたいけどモデル名わからんよというときに`--grep`と組み合わせてみるととても使える。

## show-method
```
[1] pry(main)> show-method ActionController::MimeResponds#resond_to
```

指定した`クラス#インスタンスメソッド`のソースが見れます。上の例だとこんな感じです。

```ruby:pry
Owner: ActionController::MimeResponds
Visibility: public
Number of lines: 8

def respond_to(*mimes, &block)
  raise ArgumentError, "respond_to takes either types or a block, never both" if mimes.any? && block_given?

  if collector = retrieve_collector_from_mimes(mimes, &block)
    response = collector.response
    response ? response.call : render({})
  end
end
```

### find-method
mainのコンテキストから`クラス名#インスタンスメソッド`のように指定すればソースが見れますが、メソッドがどこで定義されているかわからないときもあります。そんな時には`find-method`が役立ちます。

```rb:pry
[1] pry(main)> find-method url_for


ActionDispatch::Http::URL.url_for

ActionController::Metal
ActionController::Metal#url_for
ActionDispatch::Routing::RouteSet
ActionDispatch::Routing::RouteSet#url_for
ActionDispatch::Routing::UrlFor
ActionDispatch::Routing::UrlFor#url_for
ActionView::Helpers::UrlHelper
ActionView::Helpers::UrlHelper#url_for
ActionView::Helpers::UrlHelper::ClassMethods
ActionView::Helpers::UrlHelper::ClassMethods#_url_for_modules
ActionView::RoutingUrlFor
ActionView::RoutingUrlFor#url_for
```

## show-source 

C言語で書かれたRubyのソースも読める[^1]。

```c:pry
[7] pry(main)> show-source String#to_i

From: string.c (C Method):
Owner: String
Visibility: public
Number of lines: 17

static VALUE
rb_str_to_i(int argc, VALUE *argv, VALUE str)
{
    int base;

    if (argc == 0) base = 10;
    else {
        VALUE b;

        rb_scan_args(argc, argv, "01", &b);
        base = NUM2INT(b);
    }
    if (base < 0) {
        rb_raise(rb_eArgError, "invalid radix %d", base);
    }
    return rb_str_to_inum(str, base, FALSE);
}
```

## show-routes
bundle exec rake routes (ルーティングをみるコマンド）相当の出力が得られる。pry上でやるので早い。

```
show-routes --grep users
```

とかして`grep`と組み合わせて使うことがほとんどだと思う。

## show-doc
ドキュメントもみれる[^1]。

[^1]: show-doc, show-sourceを使うには[pry-doc](https://github.com/pry/pry-doc)というプラグインが必要です。

```rb:pry
[6] pry(main)> show-doc Enumerable#take

From: enum.c (C Method):
Owner: Enumerable
Visibility: public
Owner: Enumerable
Visibility: public
Visibility: public
Signature: take(arg1)
Number of lines: 5

Returns first n elements from enum.

   a = [1, 2, 3, 4, 5, 0]
   a.take(3)             #=> [1, 2, 3]
   a.take(30)            #=> [1, 2, 3, 4, 5, 0]
```

# デバッグ
デバッグもできる。

## binding.pry
`pry-byebug` というgemを使うと、コードに挿入して実行するとそこで止まってpryからいろいろみれる。

```ruby
...
def index
  @user = User.find params[:id]
  binding.pry
end
```

また、`whereami` あるいは `@` で、自分がいる場所を表示できる。オブジェクトの中身を見たりして画面が埋まってしまったときに便利。

## cd でクラス内部に入ってから show-method
`cd`でクラスの内部に入れる。

たとえばPostモデルというのがあったとして、その中で呼ばれている何かしらのメソッド定義を知りたい。だけどそれがどこで定義されているのかがわからないという問題がよくある。

こういうときに、クラス内部へ`cd`で入ってから`show-method`でメソッドの定義を調べるということができる。

```
pry(main)> cd Post
pry(Post):1> show-method belongs_to

From: /Users/foo/bar/vendor/bundle/ruby/2.2.0/gems/activerecord-4.1.14/lib/active_record/associations.rb @ line 1432:
Owner: ActiveRecord::Associations::ClassMethods
Visibility: public
Number of lines: 4

def belongs_to(name, scope = nil, options = {})
  reflection = Builder::BelongsTo.build(self, name, scope, options)
  Reflection.add_reflection self, name, reflection
end

```

クラスの内部に...と書いたけど、オブジェクトに入れる。

```
pry(main) user = User.find 1
pry(#<Model::User>):1> cd user
```

これでほぼなんでも見れる(はず)。

## .rails s

`.`をつけると普通のシェルコマンドも実行できるらしい。

なので、ちょっとサーバー立ち上げようとか、rspec走らようみたいなことをpry停止せずにできそう。

# Pryに自作コマンドを定義する方法
Pryは素でも機能が充実しています。しかし、時折Pryを停止したり離れたりしてからRailsアプリに対する作業を行っているときに、「あれ、これPryからできたら嬉しいんじゃ...」と思うことがあります。そういうものに関しては自作コマンドを定義したいですよね。定義しましょう。

といっても簡単で、.pryrcというコマンド定義のファイルをプロジェクト直下に置くだけです。

```rb:.pryrc
command_set = Pry::CommandSet.new do
  command "hello", "ハロー" do |name|
    puts "hello, #{name}"
  end
end
Pry.config.commands.import command_set
```

```rb:pry
[1] pry(main)> hello :gaaamii
hello, gaaamii
```

# その他
## Helperのメソッド呼びたい
`helper.`でいける。

@kzy52 さんに教えてもらいました。

- https://twitter.com/kzy52/status/820623044645253120

余談だけど、`helpers`でアクセスしようとして「うまくいかね〜な〜」ということが何度もあった。

# 補足: 日本語文字化け問題
- @yururit さんに以下のリンクを教えていただきました :sushi: 
    - [[Ruby] pryやirbで日本語入力を可能にする](http://qiita.com/kidach1/items/d0137d96bed9ac381fd5)

# 今後書き足したいこと
- ある程度実用性のある自作コマンドを作ってサンプルとして置く
- 活用例の紹介
- gifを足してわかりやすくする

___

# 参考
- [今更聞けないpryの使い方と便利プラグイン集](http://qiita.com/k0kubun/items/b118e9ccaef8707c4d9f)
- [rake routesよりshow-routesの方がはやい](http://lisp719.hatenablog.com/entry/2014/01/06/234149)
- [[Ruby] Pry $(show-source/show-method)　の使い方](http://qiita.com/yui-knk/items/ed06441ab160bc84f05f)
- [Pryが真の力を発揮してくれる19個のコマンドとコマンドの自作方法[Rails]](http://morizyun.github.io/blog/pry-command-rails-ruby/)
- [Custom commands - pry/pry/wiki](https://github.com/pry/pry/wiki/Custom-commands)