※現在、ブログ記事を移行中のため一部表示が崩れる場合がございます。
順次修正対応にあたっておりますので何卒ご了承いただけますよう、お願い致します。

RailsのDebug環境を改善する


2013年 05月 19日

皆さん、Railsの開発でデバッガ使ってますか? 私は最近ようやく使うようになりました。

それまでは、Rubyistなら誰もがやっているであろう、ppデバッグ(ppで変数を表示)のみでデバッグを行なっていました。
C#でプログラムを開発していた頃は、

  • 「デバッガ無しで開発とかありえない!大きなプロジェクトでppデバッグとか、そんな手法使えるわけないだろ」

と思っていましたが、Rubyだとデバッガ無しでも案外なんとかなってしまいます。
ppを埋め込んで変数を表示、などもお手軽にできるのが、軽量言語の素晴らしい所でもあると思います。

しかし、流石にプロジェクトの規模が大きくなるに連れて、ppデバッグだけではプログラムの流れを追いにくい、という問題に直面していました。
エラーがどこで発生したのかを確認するために、ppを至る所に埋め込んでデバッグ。そんな手法に限界を感じていた、ある日、同じプロジェクトのメンバーがBetter Errorsという素晴らしいデバッガを紹介してくれました。
このデバッガを一度使ってしまったら、もうppデバッグなんてバカらしくてやってられなくなりました。

Rubyでもデバッガは必要です。今回はRubyで使える便利なデバッガ達を紹介します。

Better Errors

Better Errorsは、Railsのエラーページを、綺麗なスタックトレース付きのものに置き換えてくれるものです。変数一覧やリクエスト情報なども出力してくれます。
さらに、ブラウザ上にREPLが表示されており、ここにRubyのコードを書くことによって、変数の中身を実行したり、書き換えたりすることもできます。

Better Errorsを導入するだけで、Debug環境が劇的に改善されることまちがいなしです。

導入もGemfileに以下のコードを追加し、bundle install するだけです。

group :development do
  gem 'better_errors'
  gem 'binding_of_caller'
end

あとはエラー発生した場合に、下図のような綺麗なエラーページが表示されます。

Better Errors

これでデバッグが捗りますね。

前回発生したエラーをもう一度参照するには、 __better_errors ページにアクセスします。
例えば、Railsが

  • http://localhost:3000/

で動いている場合は、

  • http://localhost:3000/__better_errors

と入力することで、前回エラーページにアクセスできます。
このページはAjaxリクエストのデバッグにも活用できます。ajax呼び出しでエラーが発生した場合、Better Errorsのエラー画面には遷移せず、そのままではデバッグできません。
ですが、このページにアクセスすることで、前回失敗していたAJAXリクエストの該当エラー箇所に遷移することができます。

better_errorsはdevelopment環境のみで利用するようにしてください。間違えてもproductionでは利用しないでください。
ブラウザ上で任意のRubyコード走らせられるんですから、productionで実行することが、どれだけ危険かはわかりますよね?

Better Errorsに関する詳しい情報は、https://github.com/charliesome/better_errors を参照してください。

debugger

Better Errorsを利用することで、Railsのデバッグ環境が改善されたはずです。
しかし、このBetter Errors、当然ながらRspecやCucumber内では利用できません。Specにウェブブラウザからアクセスとかできませんもんね。
Specを書いている時も、デバッガが使いたくなるときがあります。そんな時は、debugger(という名前のデバッガ)を利用しましょう。

debuggerを利用するには、以下の様な設定をGemfileに追加し、bundle installしてください。

gem ‘debugger’

後は、以下のようにテストしたいコードにdebuggerというコードを埋め込み、specを動かすことで、コンソール上でデバッガが立ち上がります。

def testfunc
  debugger  # <- ここをspecが通過することでデバッガが起動する
  xxx
end

specファイル内にもdebuggerは埋め込めますし、controllerやmodel等のソースに埋め込んでデバッグなんかもできます。

debuggerは下図のような感じで動作します。

spec_debug.png

特定のスペックの特定のテストケースを実行する方法 とうまく組み合わせて、デバッグを行なってください。

debuggerの詳しい使い方は割愛しますが、p xxx で画面に変数等のデバッグ情報表示、listでソース表示、nで次の行へ、sでステップ実行 が行えます。その他のコマンドは、デバッガが立ち上がった後にhelpと入力して確認してください。

pry-debugger

debbugerがあればSpecのデバッグも行えました。ただ、debuggerは見た目がどうしても古臭い感じがしますよね。もうちょっとカラフルに情報を表示して欲しいところです。

そんなあなたには、pry-debuggerがお勧めです。導入は以下のコードをGemfileに追加して、bundle installするだけです。

gem 'pry'
gem 'pry-rails'
gem 'pry-debugger'
gem 'pry-doc'

デバッガの本体は pry-debugger です。
pry-railsはrails consoleをpryに置き換えるものです。今回のデバッグの話題にはあまり関係ないですが、入れたほうが便利です。

あとは、デバッグしたい箇所に binding.pry を埋め込んでspecを実行するだけです。下図のようなカラフルなデバッガが立ち上がります。

pry_debugger.png

pry-debuggerの場合は、変数を表示させたい時も、debuggerの時とは違い、p ほにゃらら の、pを入力する必要はありません。
continue, step, next, finish と入力することで、debuggerの時と同様なステップ実行もできます。

ただ、debuggerと違い、sと入力したらstepにはなってくれません。毎回stepなんて打つのは面倒なので、~/.pryrc ファイルを作成し、以下のエイリアスを設定しておきましょう。

Pry.commands.alias_command 'c', 'continue'
Pry.commands.alias_command 's', 'step'
Pry.commands.alias_command 'n', 'next'
Pry.commands.alias_command 'f', 'finish'

pry-debuggerの詳細は、 https://github.com/nixme/pry-debugger を参照してください。

IDEを使ったデバッグ

RubymineなどのIDEには、標準でVisual Studioライクなデバッガが付いているようです。
しかし私は試したことがありません。

Rubyの開発ではIDEを使わなくても(Vim / Emacs / Textmate だけでも)なんとかなるものですが、IDEにはIDEの便利なところがあるとも思っています。
デバッガもdebuggerやpry-debuggerを使うより、IDEを使った方が圧倒的に便利なのかもしれません。

IDEを使ったデバッグについては、現在調査中です。
Windows環境でRubymine動かしてみたのですが、見た目がダサくて使う気がなくなってしまいました。ただ、同じプロジェクトのメンバーが、最近MacでRubymineを試験的に導入して、開発を行なっていました。
Mac版は見た目が綺麗だったので、これなら使ってみようという気になる出来でした。ただ、Rubymineのemacsキーバインディングがおかしくて使いにくい、とも言っていましたが。。。

しばらくしたら、「RailsでIDEを使ってデバッグしないとか、ありえない!」とかいう記事を書いているかもしれません。