読者です 読者をやめる 読者になる 読者になる

irb代替ツール Pry(応用編)

Rails Ruby

irb代替ツール Pryの応用編です。

この記事では、

で確認しています。

前回の復習

前回は、Pryのインストールをやって、Rails環境でも使えることをやりました。コマンドは、

tsubame.local{miyohide}% pry -r ./config/environment
[1] pry(main)>

でOK。

スコープ変更の「cd」

Pryには、cdというコマンドがあります。スコープの変更というらしいのですが、動作を見たほうが早いでしょう。まず、起動した直後、Taskモデルに対するallメソッドを実行するには、

[3] pry(main)> Task.all
=> [#<Task id: 1, name: "hgehoge", created_at: "2012-03-25 10:41:18", updated_at: "2012-03-25 10:41:18">]
[4] pry(main)> 

とします。その後、cdコマンドを実行します。

[4] pry(main)> cd Task
[5] pry(Task):1> 

すると、次からは、Taskクラスの中にスコープが移動し、Task.allを実行したい場合は、allだけでOKとなります。

[5] pry(Task):1> all
=> [#<Task id: 1, name: "hgehoge", created_at: "2012-03-25 10:41:18", updated_at: "2012-03-25 10:41:18">]
[6] pry(Task):1> 

賢いのは、Task.allと打ってもOKなところ。

[6] pry(Task):1> Task.all
=> [#<Task id: 1, name: "hgehoge", created_at: "2012-03-25 10:41:18", updated_at: "2012-03-25 10:41:18">]
[7] pry(Task):1> 

cdはネストできるから、Task.firstの中に入ることも可能。

[10] pry(Task):1> cd first
[11] pry(#<Task>):2> name
=> "hgehoge"
[12] pry(#<Task>):2> 

自分がどこにいるかを分からなかったら、selfやnestingを使えば良いです。

[12] pry(#<Task>):2> self
=> #<Task id: 1, name: "hgehoge", created_at: "2012-03-25 10:41:18", updated_at: "2012-03-25 10:41:18">
[13] pry(#<Task>):2> nesting
Nesting status:
--
0. main (Pry top level)
1. Task
2. #<Task>
[14] pry(#<Task>):2> 

今のスコープから抜けたい場合は、exitを打つと、一段上に移ります。

[13] pry(#<Task>):2> nesting
Nesting status:
--
0. main (Pry top level)
1. Task
2. #<Task>
[14] pry(#<Task>):2> exit
=> #<Task id: 1, name: "hgehoge", created_at: "2012-03-25 10:41:18", updated_at: "2012-03-25 10:41:18">
[15] pry(Task):1> nesting
Nesting status:
--
0. main (Pry top level)
1. Task
[16] pry(Task):1> exit
=> Task(id: integer, name: string, created_at: datetime, updated_at: datetime)
[17] pry(main)> nesting
Nesting status:
--
0. main (Pry top level)
[18] pry(main)> 

デバッグ

これまでRailsアプリケーションのデバックでは主にputsを使っていたのですが、それもPryを導入することで卒業となりそうです。ソース内にbinding.pryと書くことで、そこで処理が止まり変数の確認ができます。実際にやってみましょう。

まずは、Gemfileの編集です。

gem 'pry', :group => :development

上の1行を追加して、bundle installすると完了です。

その後、止めたいところにbinding.pryを挿入すると良いです。例えば、以下はscaffoldで作ったControllerのindexメソッドのところに挿入してみました。

class TasksController < ApplicationController
  def index
    @tasks = Task.all
    binding.pry

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @tasks }
    end
  end
  # 以下省略

後は、rails sでサーバを起動し、ブラウザでアクセスすると、コンソール上には次の表示が出ます。

tsubame.local{miyohide}% rails s [~/work/RailsSample/capybara/
=> Booting WEBrick
=> Rails 3.2.2 application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
[2012-03-31 18:21:22] INFO WEBrick 1.3.1
[2012-03-31 18:21:22] INFO ruby 1.9.2 (2011-07-09) [x86_64-darwin11.1.0]
[2012-03-31 18:21:22] INFO WEBrick::HTTPServer#start: pid=1144 port=3000

From: /Users/miyohide/work/RailsSample/capybara/todo/app/controllers/tasks_controller.rb @ line 6 in TasksController#index:

1: class TasksController < ApplicationController
2: # GET /tasks
3: # GET /tasks.json
4: def index
5: @tasks = Task.all
=> 6: binding.pry
7:
8: respond_to do |format|
9: format.html # index.html.erb
10: format.json { render json: @tasks }
11: end

[1] pry(#)>

例えば、@tasksの中を確認してみましょう。

[1] pry(#<TasksController>)> puts @tasks
#<Task:0x007fd046d6d148>
=> nil
[2] pry(#<TasksController>)> puts @tasks.inspect
[#<Task id: 1, name: "hgehoge", created_at: "2012-03-25 10:41:18", updated_at: "2012-03-25 10:41:18">]
=> nil
[3] pry(#<TasksController>)>

デバッグには強力に役立ちそうですね。

終了させるには、exit-allとすると処理が進みます。

[3] pry(#)> exit-all


Started GET "/tasks" for 127.0.0.1 at 2012-03-31 18:21:33 +0900
Processing by TasksController#index as HTML
Task Load (0.2ms) SELECT "tasks".* FROM "tasks"
…(以下省略)

まとめ

個人的には、binding.pryが超便利。ま、putsデバックなんて邪道、ちゃんとテストコード書けよって言われそうですが、ま、いろいろありまして・・・^^;

参考

RailsCasts #280。新幹線内で動画見てたとき、binding.pryのところで思わず「これ、すげぇ」って声上げてしまいました。