Railsアプリのデバッグ手段をまとめます。Docker Compose上でRailsアプリを動かしている場合でも使える方法です。
1.ppを使う
以下のようにppでデバッグしたい変数を出力します。結論としてはこれで十分なことが多そうです。
基本形
コード
class TagsController < ApplicationController # 省略 def index # 省略 tag_ids = Array(params[:tag_ids]).reject(&:blank?) pp "🐛params=#{tag_ids}" # 省略 end # 省略 end
結果
私の環境ではDocker Compose上でRailsアプリを動かしていますが、それでも以下のように標準出力に値が出力されます。
web-1 | "🐛params=[\"1\", \"2\"]"
ActiveRecordの検索結果のデバッグ
ActiveRecordの検索結果も以下のようにデバッグできます。
単数の場合
コード
pp "🐛tag_group=#{@tag_group.as_json}"
結果
web-1 | "🐛tag_group={\"id\" => 1, \"name\" => \"テスト\", \"position\" => 1, \"created_at\" => \"2025-11-02T14:58:36.249Z\", \"updated_at\" => \"2025-11-02T14:58:36.249Z\"}"
複数の場合
コード
@tag_groups = TagGroup.all pp "🐛tag_groups=#{@tag_groups.as_json}"
結果
web-1 | "🐛tag_groups=[{\"id\" => 1, \"name\" => \"テスト\", \"position\" => 1, \"created_at\" => \"2025-11-02T14:58:36.249Z\", \"updated_at\" => \"2025-11-02T14:58:36.249Z\"}, {\"id\" => 3, \"name\" => \"料理\", \"position\" => 2, \"created_at\" => \"2025-11-03T01:57:30.807Z\", \"updated_at\" => \"2025-11-03T01:57:30.807Z\"}]"
※ as_jsonは単にデータをJSONにダンプして見やすくしているだけではなく、ActiveRecordのデータ取得を実行する意味があります。
pp "🐛tag_groups=#{@tag_groups}"とすると以下のようにデータ取得前のActiveRecord::Relationをデバッグしてしまい、ほしい結果が得られません。
web-1 | "🐛tag_groups=#<TagGroup::ActiveRecord_Relation:0x0000ffff95b76d68>"
2.デバッグログを使う
ppの代わりにlogger.debugを使います。Railsガイドで紹介されている方法です。
railsguides.jp
JSONのダブルクォートのエスケープが消えて少し見やすいですが、ppの方がタイピングしやすいメリットもあるので、一時的なデバッグであればどちらを使うかは好みの問題な気がします。
コード
@tag_groups = TagGroup.all logger.debug "🐛tag_groups=#{@tag_groups.as_json}"
結果
web-1 | 🐛tag_groups=[{"id" => 1, "name" => "テスト", "position" => 1, "created_at" => "2025-11-02T14:58:36.249Z", "updated_at" => "2025-11-02T14:58:36.249Z"}, {"id" => 3, "name" => "料理", "position" => 2, "created_at" => "2025-11-03T01:57:30.807Z", "updated_at" => "2025-11-03T01:57:30.807Z"}]
(補足)SQLログを無効にする
Railsはデフォルトで以下のようにリクエスト時に発行されるSQLがコンソールにロギングされます。
web-1 | Tag Load (0.3ms) SELECT "tags".* FROM "tags" INNER JOIN "restaurants_tags" ON "tags"."id" = "restaurants_tags"."tag_id" WHERE "restaurants_tags"."restaurant_id" = 1 /*action='index',application='App',controller='restaurants'*/
これがノイズになってプリントデバッグで出力したログが埋もれることがありました。
その場合は一時的に以下の設定をすることで、SQLログを抑制することができます。
config/environments/development.rb
Rails.application.configure do # ... config.active_record.logger = nil # ... end
参考
todo: ステップ実行
ステップ実行についても書こうと思ったのですが、それだけで大きなテーマになりそうなので別の記事にします。