【結論】
・binding.pryをeachなどのループ処理内に記述すると、
exitを実行しても、何度も同じ処理が呼び出され、
ループ処理から直ぐに抜けられない
・ループ処理から抜ける為に
「exit!・exit-program・!!!・disable-pry」
というコマンドが存在する
・binding.pryに条件式を組み込む事で
任意のタイミングだけ止める方法もある
【目次】
- pryの使い方を一割しか知らなかったという話
- pryとは
- binding.pryの使い方
- ループ処理について
- exit!・exit-program
- !!!
- disable-pry
- 条件式
- 結局どれが良いのか?
- 《今日の学習進捗(3年以内に10000時間に向けて)》
【本題】
pryの使い方を一割しか知らなかったという話
Railsでのデバックといえば、pry-byebugを用いた方法が一般的で、
私もデバックで多用していました。
私の場合、「binding.pry」で任意の場所(コード)で処理を止めて、
そこからデバックを行うという方法しか知らなかったのですが、
他にも、もっと色んな便利機能があると、
この前に行った勉強会で教えてもらったので、今回はそれをまとめます。
pryとは
そもそもpryとは何か?ですが、REPLの一種。
REPLとは、対話型実行環境のこと。
Read-Eval-Print-Loopの略で、
読込(Read)→実行(Eval)→出力(Print)→待機(Loop)
という一連のサイクルを表している。
Rubyの場合は、ターミナルで「irb」を実行した時に
出来る事がREPLにあたる。
↓irb
そして、「irb」より高性能なREPLが「pry」
「pry-byebug」というプラグインを用いる事で、
RailsのアプリケーションをREPLで実行して、
デバックを行う事が出来る。
binding.pryの使い方
まず、基本のbinding.pryの使い方からおさらいします。
「binding.pry」というコードを記述すると、
アプリケーションの実行を記述した場所で止めて、
REPLで動作を検証する事が出来ます。
止めた状態で、変数の値を確かめたり、
変数に別の値を代入して、その後の処理が正常に進むかなどを確認できます。
実際に使い方を見ていきます。
コントローラーやモデルなどで使用する場合は、
止めたい箇所に「binding.pry」を記述します。
※ビューで使用する場合は、他のRuby文と同じように<% %>で囲います。
※下記はHamlのコードなので、先頭に「-」を記述しています。
記述後、コードが書かれたページにアクセスすると、
ターミナル上で、pryが起動し、入力待ちの状態になります。
その状態で任意の変数を入力し、実行すると、値を確認できます。
「exit」を実行すれば、REPLから抜けられます
ループ処理について
「binding.pry」を使用する際に困るのは、
ループ処理内に記述した場合、
何度も処理が呼び出されてしまう事です。
例えば、下記の様に「binding.pry」を記述したとします。
each文の中に記述されていますが、この場合、
処理を止めて内容をチェックしてから「exit」で抜けようとしても、
再度each文で「binding.pry」が読み込まれてしまい、何度も処理が止まる事になります。
では、その様な場面での対処方法を紹介します。
exit!・exit-program
これはpryのコマンドの一種で、
rails server自体を強制的に終了させます。
もう一度サーバーを再起動し直す必要がありますが、
ループから抜ける事が可能です。
!!!
このコマンドは、rails serverは終了させず、
binding.pryで設定したブレークだけ終了させて、ループを抜けられます。
但し、例外で終了する様で、その後の処理でエラーが発生します。
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
「!!!」で終了させた後に、「binding.pry」を削除して、
再度ページを読み込み直せば、エラーは解消されます。
なお、pryで「edit -m」というコマンドを実行すれば、
ターミナル上でファイルの編集が可能です。
disable-pry
rails serverは終了させず、binding.pryで設定した
ブレークだけ終了させて、ループを抜けられます。
例外にならずに処理を継続させる事が可能です。
但し、pry自体がその後、機能しなくなり、
再度binding.pryで処理を止めたい場合は、サーバーを再起動させる必要があります。
条件式
最後は、binding.pryに条件式を組み込んで、
pryが起動するタイミングを任意にコントロールする方法です。
例えば、下記の様に条件式を記述します。
binding.pry unless @num == 1
@numは、binding.pry新たに定義したインスタンス変数なので、
初めの値は「nil」になります。
これでpryが起動した後に、@numに「1」を代入すれば、
その後は条件式でbinding.pryを読み込まなくなるので、
「exit」だけでループ処理を抜ける事が可能です。
また、@numなどのインスタンス変数を新たに定義するのではなく、
既存のインスタンス変数で条件式を組めば、
特定の値が入った場合だけ、処理を止めるという応用も可能です。
この方法であれば、サーバー再起動やページの再読込みは不要です。
結局どれが良いのか?
いずれも一長一短ありますが、最もスムーズに処理が出来るのは、
条件式を組み込む方法だと考えています。
但し、条件式を組み込みのが面倒だったり、組み込むのを忘れてしまって
ループ処理で止まった際などは、「!!!」でブレークだけ終了させた後に、
コードを書き換える方法が良いと思われます。
《今日の学習進捗(3年以内に10000時間に向けて)》
学習開始からの期間 :99日
今日までの合計時間:945h
一日あたりの平均学習時間:9.6h
今日までに到達すべき目標時間:904h
目標との解離:41h
「10,000時間」まで、
残り・・・「9055時間!」