Pry/IRBでのデバッグテクニック
Rubyのプログラミングにおいて、デバッグは避けて通れないプロセスです。幸い、RubyにはIRB (Interactive Ruby) と、それをさらに強力にしたPryという、優れたREPL (Read-Eval-Print Loop) ツールが付属しており、これらを活用することでデバッグ作業を効率的に進めることができます。
IRB: Rubyの標準REPL
IRBはRubyに標準でバンドルされている対話的実行環境です。ターミナルでirbと入力するだけで起動し、Rubyのコードを一行ずつ実行して結果を確認できます。
irb
irb(main):001:0> 1 + 2
=> 3
irb(main):002:0> "hello".upcase
=> "HELLO"binding.irb: 実行中のコードに割り込む
Ruby 2.4から、binding.irbという非常に便利なデバッグ機能が追加されました。コードの中の好きな場所にbinding.irbと記述すると、プログラムの実行がその場で一時停止し、IRBセッションが起動します。
# user.rb
class User
def initialize(name, age)
@name = name
@age = age
end
def greeting
message = "Hi, I'm #{@name}."
binding.irb # ここで実行が一時停止する
puts message
end
end
user = User.new("Alice", 30)
user.greetingこのコードを実行すると、binding.irbの行で停止し、ターミナルがIRBプロンプトに切り替わります。このスコープ内では、その時点での変数や状態に自由にアクセスできます。
From: user.rb @ line 10 User#greeting:
5: def greeting
6: message = "Hi, I'm #{@name}."
=> 7: binding.irb
8: puts message
9: end
irb(main):001:0> message
=> "Hi, I'm Alice."
irb(main):002:0> @name
=> "Alice"
irb(main):003:0> self
=> #<User:0x00007f9b1a0b3d40 @name="Alice", @age=30>
irb(main):004:0> @age += 1
=> 31
irb(main):005:0> exit # または Ctrl+D でIRBを終了し、プログラムの実行を再開exitコマンドでIRBを抜けると、プログラムは停止した次の行から実行を再開します。
Pry: さらに強力なREPL
Pryは、IRBを大幅に機能強化したGemです。シンタックスハイライト、コードのインデント、より詳細なオブジェクトの表示、ソースコードの閲覧など、多くの便利な機能を備えています。
インストール
Gemfileに追加してインストールします。デバッグ用のツールなので:developmentグループに入れるのが一般的です。
# Gemfile
group :development do
gem 'pry'
gem 'pry-byebug' # ステップ実行などの機能を追加
gem 'pry-rails' # RailsコンソールをPryに置き換える
endbundle installbinding.pry: Pryで割り込む
binding.irbと同様に、コード内にrequire 'pry'を記述した上でbinding.pryと書くと、その場でPryセッションが起動します。
require 'pry'
class Calculator
def add(a, b)
result = a + b
binding.pry # ここでPryが起動
result
end
end
calc = Calculator.new
calc.add(5, 3)Pryセッションでは、IRBの機能に加えて以下のような強力なコマンドが使えます。
Pryの主要コマンド
ls: 現在のスコープで利用可能な変数やメソッドの一覧を表示します。ls -v: インスタンス変数やローカル変数を表示。ls -m: メソッドの一覧を表示。ls MyClass:MyClassのメソッドや定数を表示。
show-doc/?: メソッドのドキュメントを表示します。show-doc Array#map? user.greeting
show-source/$: メソッドのソースコードを表示します。show-source User#greeting$ user.greeting
cd: コンテキスト(self)を別のオブジェクトに変更します。これにより、そのオブジェクトの内部を探索するのが容易になります。[1] pry(main)> cd user [2] pry(#<User>):1> ls -v @age: 30 @name: "Alice" [3] pry(#<User>):2> exit # 元のコンテキストに戻るwhereami: 現在のコードの場所(ファイル名と行番号)をソースコード付きで表示します。
ステップ実行 (pry-byebug)
pry-byebugを導入すると、ブレークポイントから一歩ずつコードを実行していくステップ実行が可能になります。
next: 次の行へ進みます。メソッド呼び出しがあっても、その中には入りません。step: 次の行へ進みます。メソッド呼び出しがあれば、そのメソッドの内部に入ります。finish: 現在のメソッド(またはブロック)の実行を終え、呼び出し元に戻るまで実行を進めます。continue: Pryセッションを終了し、次のブレークポイントかプログラムの終わりまで実行を続けます。
require 'pry'
require 'pry-byebug'
def method_a
puts "Start of method_a"
x = 10
method_b(x)
puts "End of method_a"
end
def method_b(num)
puts "Start of method_b"
binding.pry # ここで停止
result = num * 2
puts "End of method_b"
result
end
method_aPryセッション内でstepと入力するとmethod_bの次の行に進み、nextを入力しても同じです。しかし、method_aのmethod_b(x)の行で停止していた場合、stepならmethod_bの内部に入り、nextならmethod_bの実行をすべて終えてputs "End of method_a"の行まで進みます。
まとめ
binding.irbは、Rubyに標準で備わっている手軽で強力なデバッグツールです。- Pry は、IRBをさらに拡張し、
ls,show-source,cdなどの豊富なコマンドで、より詳細なデバッグを可能にします。 pry-byebugを使えば、next,stepなどのコマンドによるステップ実行が可能になり、コードの流れを一行ずつ追跡できます。
これらのREPLツールを使いこなすことで、putsデバッグ(変数の中身をputsで表示して確認する方法)から脱却し、プログラムの内部状態を対話的に調査しながら、より迅速かつ正確に問題を特定できるようになります。