【Rails】pry-byebugの使い方・終了方法を解説!効率よくデバッグしよう

当サイトでは一部リンクに広告が含まれています
アイキャッチ

プログラミングの世界において、コードはときに思うように動作せず、それが原因で思わぬバグが発生します。
しかし、そんなときに強力な助けとなるツールがあります。
それが、Ruby on Rails開発でよく使われるデバッグツール、pry-byebugです。

https://github.com/deivid-rodriguez/pry-byebug

本記事では pry-byebugの使い方と、その便利さを詳しく解説します。

pry-byebug を使うとコードの一部を止めたり、一行ずつ実行したり、変数の値を確認したりと、バグを特定し修正するための作業を格段に効率的に行うことができます

また、デバッグ中に経験する可能性のある問題、例えば、コードが予期せぬ場所で停止してしまったり、デバッグセッションを終了できなくなったりする等の問題への対処法もご紹介します。

プロの開発者から初学者まで、pry-byebugはRuby on Rails開発において欠かせないツールと言えます。
実際、著者が働いている会社では、pry-byebugを使ってデバッグを行うことが日常茶飯事です。

本記事を参考に、デバッグスキルをさらに磨き上げていきましょう!

目次

pry-byebugの導入と使い方

pry-byebugのインストール

最初にpry-byebugを導入します。pry-byebugはRubyやRailsで使うことができる便利なデバッグツールです。

デバッグとは、コードのエラーを見つけて修正する作業のことです。

まず、Gemとして導入します。GemはRubyのライブラリで、特定の機能を提供します。

Gemfileに以下の行を追加します。

gem 'pry-byebug'

次に、コマンドラインで bundle install を実行します。これでpry-byebugがインストールされます。

pry-byebugの基本的な使い方

pry-byebugを使うと、コードの任意の行で実行を一時停止し、その時点の状態を詳しく調べることができます。これはブレークポイントを設定するということです。

例えば、以下のように書いてみます。

def some_method
  a = 1
  binding.pry
  b = 2
end

binding.pry の行でコードの実行が一時停止します。その後、コンソール(ターミナル)には現在の変数の状態や使用可能なメソッドなどが表示されます。そして、次のコマンドを入力することでさまざまな操作を行うことができます。

  • next: 次の行に移動します。
  • step: メソッドの内部に移動します。
  • continue: 実行を再開します。

これにより、プログラムが期待どおりに動作しているか、変数には期待どおりの値が格納されているかなどを確認できます。

具体的なソースコードとともに学ぶpry-byebugの使用法

例えば、次のようなコードがあるとします。

def add_numbers(a, b)
  sum = a + b
  puts sum
end

ここで binding.pry を使って a + b の結果を確認したいときは、次のようにします。

def add_numbers(a, b)
  sum = a + b
  binding.pry # ここに追加
  puts sum
end

これを実行すると、sum = a + b の行の後にpryのセッションが開始されます。そして、sumという変数にどのような値が格納されているかを直接確認できます。

さらに、この状態では任意のRubyのコードを実行することができます。例えば、sum * 2を実行してsumの値の2倍の値を確認することも可能です。

このように、pry-byebugを使うとコードの途中で処理を停止させ、変数の値を確認したり、任意のコードを実行したりすることができます
これにより、コードの動作を詳しく理解したり、バグの原因を特定したりすることができます。

具体例で学ぶpry-byebugの使い方

それでは、具体例を見ながらpry-byebugの使い方を学んでいきましょう。

具体例1: コントローラーのデバッグ1

まずは、Railsのコントローラーでのデバッグ方法を見ていきましょう。例えば、以下のようなコードがあるとします。

class UsersController < ApplicationController
  def index
    @users = User.all
  end
end

このコードでは、すべてのユーザーを取得して、それをインスタンス変数 @users に格納しています。ここで、 User.all の結果が正しいか確認したい場合、 binding.pry を使って以下のように書くことができます。

class UsersController < ApplicationController
  def index
    @users = User.all
    binding.pry
  end
end

これを実行すると、 User.all の後にコードの実行が一時停止します。

例:

# コードが一部表示される
From: /Users/username/rails_app/app/controllers/users_controller.rb @ line 3 UsersController#index:

    1: class UsersController < ApplicationController
    2:   def index
 => 3:     @users = User.all
    4:     binding.pry
    5:   end
    6: end

[1] pry(#<UsersController>)>

その状態でターミナルに @users と入力すると、 @users の値が表示されます。これにより、 User.all の結果が期待通りであることを確認できます。

例:

[1] pry(#<UsersController>)> @users
=> [#<User:0x00007f8f9c0b1b00
  id: 1,
  name: "Alice",
  ...

このように、 binding.pry を使うことで、コードの実行を一時停止して、その時点での変数の値を確認することができることが最大の特徴です。

具体例2: コントローラーのデバッグ2

次に、複数の操作を行った後の結果を確認する例を見てみましょう。例えば、以下のようなコードがあるとします。

class UsersController < ApplicationController
  def update
    @user = User.find(params[:id])
    @user.update(user_params)
    binding.pry
  end

  private

  def user_params
    params.require(:user).permit(:name, :email)
  end
end

このコードでは、指定されたIDのユーザーを探し、そのユーザーの情報を更新しています。 binding.pry を使うことで、更新後の @user の状態を確認することができます。

例:

From /Users/username/rails_app/app/controllers/users_controller.rb @ line 4 UsersController#update:

    3: def update
 => 4:   @user = User.find(params[:id])
    5:   @user.update(user_params)
    6:   binding.pry
    7: end

[1] pry(#<UsersController>)> @user
=> #<User:0x00007f8f9c0b1b00
  id: 2,
  name: "Alice",
  ...

具体例3: モデルのデバッグ

モデルでも同様に binding.pry を使ってデバッグすることができます。例えば、以下のようなコードがあるとします。

class User < ApplicationRecord
  def change_name(name)
    self.name = name
    save
    binding.pry
  end
end

このコードでは、ユーザーの名前を変更して保存しています。 binding.pry を使うことで、保存後のユーザーの状態を確認することができます。

例:

From /Users/username/rails_app/app/models/user.rb @ line 4 User#change_name:

    3: def change_name(name)
    4:   self.name = name
    5:   save
=>  6:   binding.pry
    7: end

[1] pry(#<User>)> self
=> #<User:0x00007f8f9c0b1b00
  id: 2,
  name: "Alice",
  ...

具体例4: ビューのデバッグ

ビューでデバッグを行うことは推奨されていませんが、ビューで利用されるデータの状態をチェックするためには有効な手段です。例えば、以下のようなコードがあるとします。

<%= @user.name %>
<% binding.pry %>

このコードでは、ユーザーの名前を表示しています。 binding.pry を使うことで、 @user.name の値を確認することができます。ただし、ビューでのデバッグは、基本的にデータの状態をチェックするためだけに使い、ロジックの修正に使うべきではありません。

例:

From /Users/username/rails_app/app/views/users/show.html.erb @ line 2 Users#show:

    1: <%= @user.name %>
 => 2: <% binding.pry %>

[1] pry(#<#<Class:0x00007f8f9c0b1b00>>) @user.name
=> "Alice"

具体例5: テストのデバッグ

テストコードでも binding.pry を使ってデバッグすることができます。例えば、以下のようなコードがあるとします。

require 'rails_helper'

RSpec.describe User, type: :model do
  it 'changes the name correctly' do
    user = User.create(name: 'Old Name', email: 'test@example.com')
    user.change_name('New Name')
    binding.pry
    expect(user.name).to eq('New Name')
  end
end

このコードでは、 change_name メソッドが正しく機能しているかをテストしています。 binding.pry を使うことで、名前を変更した後のユーザーの状態を確認することができます。

例:

From /Users/username/rails_app/spec/models/user_spec.rb @ line 6 User changes the name correctly:

    5: user = User.create(name: 'Old Name', email: 'tom@hoge.com')
    6: user.change_name('New Name')
 => 7: binding.pry
    8: expect(user.name).to eq('New Name')

[1] pry(#<RSpec::ExampleGroups::User::UserChangesTheNameCorrectly>)> user
=> #<User:0x00007f8f9c0b1b00
  id: 2,
  name: "New Name",
  ...

よくある問題と解決策(Railsでbyebugが止まらない・終了できない等)

次に、pry-byebugを使っているときによく遭遇する問題と、それぞれの解決策について見ていきましょう。

byebugを強制終了したい

デバッグ中に強制的に終了したい場合は、 exit と入力します。
これにより、現在のデバッグセッションを終了してコードの実行を再開します。

例:

[1] pry(#<UsersController>)> exit

binding.pryを使っても止まらない

binding.pry を使ってもコードが止まらない場合、まずは pry-byebug が正しくインストールされているか、そしてRailsのアプリケーションで読み込まれているか確認しましょう。
以下のようにGemfileをチェックして、 pry-byebug が含まれているか確認します。

group :development, :test do
  gem 'pry-byebug'
end

このように pry-byebugdevelopmenttest のグループに含めて、 bundle install を実行しましょう。

他には、例えば if 文で条件分岐されていたり、return の後に binding.pry を書くと、そもそも binding.pry を通過せずに処理が進んでしまいます。
この場合にも処理が途中で止まりませんので、ご注意ください。

binding.pryを強制終了したい

!!! と入力することで、 binding.pry を強制終了することができます。

例:

[1] pry(#<UsersController>)> !!!

exit との違いは、 exit は現在のデバッグセッションを終了してコードの実行を再開しますが、 !!! は現在のデバッグセッションを終了してコードの実行を終了します。
そのため、強制終了したい場合は !!! を使いましょう。

よくある質問

最後に、よくある質問について見ていきましょう。

pry-byebugとpry-railsの違いは?

pry-rails はRailsのコンソール環境をPryに置き換えるGemです。これにより、RailsコンソールでPryの強力な機能を利用できます。

一方、 pry-byebug はPryというREPL(コードを一行ずつ実行して結果を表示するツール)に、デバッグ機能を追加するGemです。コードの一部を停止させたり、ステップ実行を行ったりすることができます。

つまり、pry-railsはRailsのコンソール操作を強化し、pry-byebugはデバッグ操作を強化します。

pry-byebugとbinding.pryの違いは?

ここでの binding.pry は、実際にはpry-byebugによって提供されるメソッドです。 binding.pry をコードに挿入すると、その位置で実行を停止してPryのREPLを開始します。このときのREPLは、 binding.pry の位置のスコープ(変数の有効範囲)で実行されるため、その位置で利用可能なすべての変数やメソッドを使用することができます。

それに対して、 pry-byebug は、この binding.pry を含むデバッグ機能を提供するGem自体を指します。

pry-byebugとpry-rescueの違いは?

pry-rescue は、例外が発生したときに自動的に binding.pry を挿入するGemです。これにより、例外が発生したときに、その場所で実行を停止してデバッグを行うことができます。

以上、RailsとPry-byebugの連携について解説しました。プログラミングにはデバッグが不可欠です。ぜひPry-byebugを活用して、効率的なデバッグを行ってください。

目次