Ruby on Rails's archives

NetBeansからRuby on Rails(RoR)のリモートデバッグ

by ginriki | 7 月 12th, 2010 

NetBeansには、rubyのデバッガフロントエンドが同梱されています。
今回は、それを使ってRuby on Rails(以下RoR)のリモートデバッグをするためのメモです。

個人的には、RoRが動いてるマシンにsshでログインした後、emacsとrubydb3x.elを使う方がメリットがある1と思いますが、emacsの場合デバッガ用GUIはありません。GUIに慣れてる人はNetBeansの方が楽なので、そういう人向けにまとめます。

なお、NetBeansをインストールしたローカルマシンで、RoRも動かす場合のデバッグ方法は、NetBeansのwikiを参照してください。

まあ、ローカルマシン上でデバッグする場合も、リモートマシンと接続してデバッグする場合もやり方はほとんど変わりません。

どちらの場合も、デバッギプロセス(と同じプロセス上で動くruby-debug-ide)がTCP(デフォルトだと1234)をListenし、Netbeansからそこに接続してデバッグを開始します。Netbeansから接続するデバッギプロセスがlocalhostにいるか、リモート先のホストにいるかの違いしかないです。
接続後、Netbeansからruby-debug-ideへbreakpointをしかける場所などを指示します。

デバッグ方法そのものは、ローカル・リモートともに一緒ですが、リモートのホストに対してローカルのNetBeansを接続してデバッグするには、リモート先のホストで以下の作業が必要です。

  1. rubyインストール (解説略)
  2. RubyGemsインストール (解説略)
  3. RoRインストール・プロジェクト作成 (解説略)
  4. ruby-debug-ideインストール
  5. リモート先のRoRプロジェクトのソースコードを、ローカルにも展開
  6. ruby-debug-ide付きでRoRプロジェクトのWebサーバ起動

4, 5, 6の手順は、あまりネット上で見かけないので順に解説します。

ruby-debug-ideインストール

Linuxだと、gemで簡単にインストールできます。(gcc, ruby-develをインストールしておけば。)
Fedora8だと以下で終わりでした。

$ gem install ruby-debug
$ gem install ruby-debug-ide

Windows(のmswin版ruby)の場合、コンパイル環境の用意が面倒なので、コンパイル済みgemをダウンロードした上でインストールします。2

> gem install -l linecache-0.43-mswin32.gem
> gem install -l ruby-debug-base-0.10.3-mswin32.gem
> del ruby-debug-base-0.10.3-mswin32.gem
> gem install ruby-debug
> gem install ruby-debug-ide -v 0.4.6

コンパイル済みgem (linecache, ruby-debug-base)は以下2つのリンク先から
それぞれダウンロードしてください。

リモート先のRoRプロジェクトのソースコードを、ローカルにも展開

ローカルにもソースコードを置かないと、breakpointで止まった時にNetbeansにソースコードが読み込まれません。
注意点としては、リモートと同じフルパス上にソースコードを置く必要がある点です。リモート先で、/var/www/railsprjにRoRのプロジェクトコードが置いてあるなら、ローカルでも/var/www/railsprjにプロジェクトコードを置く必要があります。3

この辺の挙動理解には、NetBeans wikiのChecking debugger engine functionalityとか、ruby-debug-ide protocolとかを参考にして、実際にruby-debug-ideとtelnetで会話するといいです。

ruby-debug-ide付きでRuby on RailsプロジェクトのWebサーバ起動

以下な感じでRoR Webサーバ起動します。(-dも付けると、NetBeansとの通信時の処理が良く見えます。)

$ rdebug-ide --stop script/server -h 0.0.0.0
Fast Debugger (ruby-debug-ide 0.4.6) listens on 0.0.0.0:1234

NetBeansからruby-debug-ideに接続

NetBeans IDEのメニュー -> デバッグ -> 接続をクリックし、ダイアログにリモート先ホスト名とポート番号(1234)を指定して接続します。
–stopを指定してあるので、RoRの処理先頭でstopするはずです。
あとは、IDEからbreakpoint指定するなり、なんなり自由に操作します。
watch変数として、paramsを追加しておくといい感じです。

  1. sshのポート(TCP 22)が開いてることは普通にありますが、デバッガ・デバッギ通信用のポートがfirewallで遮断されることは良くあります。 []
  2. 最近だと、Visual C++は無料で手に入りますがmswin版rubyをコンパイルしたVisual C++と同じバージョンをインストールする必要しないと「MSC version unmatch」エラーが出てめんどくさいです。http://rubyforge.org/tracker/index.php?func=detail&aid=16774&group_id=1900&atid=7436 []
  3. WindowsとLinuxだとフルパスを一致させることが不可能なので、例えば、Windows上のNetBeansからLinux上のRoRがデバッグができないという点でかなりアレな仕様です。誰もやってないなら修正パッチ作るかな。 []

autoloadで自動読み込みされないファイルをユーザアクセス毎に再読み込みする

by ginriki | 12 月 31st, 2009 

今回はRuby on Railsについてメモ。

autoloadで自動読み込みされないファイル1をcontrollerの中などでrequireを使って読み込んだ場合、そのファイルはdevelopmentモード時でもユーザアクセス毎に再読み込みされません。そのため、ファイルを編集してもwebサーバを再起動しないと変更が反映されないので、デバッグがやりづらくて困ってました。

解決策がないかと思って、ググってみたところ、以下のページに解決策が書いてありました。
http://www.pistolfly.jp/weblog/2007/06/require-dependency.html

requireじゃなくて、require_dependencyでファイル読み込みすれば良いということでした。
require_dependencyの挙動については、上のリンク先を参照してください。
この辺り(autoload周辺)って、Ruby on Rails公式なドキュメントが見当たらないですねえ。・・・実装を読めってことか。

以下、問題のコード例と解決方法。(ruby 1.8.5, rails 2.3.3, WEBrick 1.3.1で実験しました。)

ファイル読み込みの対象となるファイルを用意します。

<rails_project>/lib/hoge_fuga.rb

RUBY:
  1. class Hoge
  2.   def hoge
  3.     return "abc"
  4.   end
  5. end

上のファイルを読み込むcontrollerを用意します。
このとき、requireの代わりにrequire_dependencyでファイルを読み込みます。

<rails_project>/app/controllers/test_controller.rb

RUBY:
  1. #require 'hoge_fuga'
  2. require_dependency 'hoge_fuga'
  3.  
  4. class TestController <ApplicationController
  5.   def hoge
  6.     a = Hoge.new
  7.     render(:text => a.hoge)
  8.   end
  9. end

んで、Webサーバを起動。

$ cd <rails_project>
$ ruby script/server

で、ブラウザからtest/hogeにアクセスすると、ブラウザ上にabcが出力されます。
この状況で、<rails_project>/lib/hoge_fuga.rbを以下のように書き換えてみます。

RUBY:
  1. class Hoge
  2.   def hoge
  3.     return "123"
  4.   end
  5. end

変更を保存した後、ブラウザからtest/hogeにアクセスすると、ブラウザ上に123が出力されます。
確かに、Webサーバを再起動しなくても、<rails_project>/lib/hoge_fuga.rbが再読み込みされてますね。

これでデバッグがしやすくなるなあ。

  1. Railsの場合、クラス定義と定義が記述されたファイルの名前が対応づいてないとautoloadで自動読み込みされません(たぶん)。例えば、FooBarというクラスの定義はfoo_bar.rbというファイルの中で行われてないとautoloadにされません。 []

ブログで紹介した商品

  • Image of デバッガの理論と実装 (ASCII SOFTWARE SCIENCE Language)