第11章 動かないときは境界を見る
第10章までで、映画図鑑は小さな CRUD アプリケーションとして一通り動く状態になりました。
この章では、新しい機能を増やしません。動かないときに、ブラウザ、HTTP、Sinatra、ERB、JSON ファイルを順に調べ、どこで問題が起きているかを事実から切り分ける方法を整理します。
まず再現手順を短くする
デバッグでは、いきなり原因を当てようとしません。まず、何をすると何が起きるのかを短くします。
例えば、次のように書ける状態を目指します。
1. /movies/new を開く。
2. タイトルに「テスト映画」と入力する。
3. 登録する。
4. 詳細画面ではなく 404 ページが表示される。
「なんか動かない」では、見る場所を決められません。URL、操作、期待した結果、実際の結果を分けます。
ブラウザの表示と Network タブを分けて見る
ブラウザに表示された画面は、結果の一部です。Web アプリケーションでは、画面の裏で HTTP リクエストとレスポンスが発生しています。
Network タブでは、次を確認します。
- URL
- HTTP メソッド
- ステータスコード
- リクエストヘッダー
- レスポンスヘッダー
- Form Data
- リダイレクト前後のリクエスト
例えば、登録後に詳細画面へ移動しない場合は、まず POST /movies が送られているかを見ます。次に、レスポンスが 303 See Other か、Location がどこを指しているかを見ます。
画面だけを見て「登録に失敗した」と決めつけないでください。data/movies.json には保存されているが、リダイレクト先の URL が間違っている、ということもあります。
Sinatra のログを見る
bundle exec ruby app.rb でアプリを起動しているターミナルには、Sinatra のログが出ます。
ログは操作するたびに増えていきます。操作の前にログの最後の行を見ておき、操作した直後に追加された行を確認すると、どの操作に対応するログなのかを見失いにくくなります。
例えば、更新時には次のようなログを確認できます。
"PATCH /movies/b6f5e1c4-4b5f-4a7f-8f8f-3d9d3ef9d001 HTTP/1.1" 303
Network タブでは POST と _method=patch が見えます。Sinatra のログでは、Rack の method override を通過した後の PATCH が見えます。
削除も同じです。
"DELETE /movies/b6f5e1c4-4b5f-4a7f-8f8f-3d9d3ef9d003 HTTP/1.1" 303
ログを見ると、どのルートまで届いたのか、どのステータスコードを返したのかが分かります。
params と JSON ファイルを見る
フォームから値が届いているかを調べるときは、params を確認します。
第4章では、確認用に次のようなコードを書きました。
post "/movies" do
content_type :text
params.inspect
end
完成コードへ戻す必要があるため、この確認用コードを残してはいけません。ただ、切り分けの考え方として、フォームの name と params のキーを見比べることは重要です。
確認用コードを入れたら、動作確認後に必ず差分を戻します。デバッグのために一時的に書いたコードを残すと、後の章で説明している完成コードと実際のコードがずれてしまいます。
保存後に問題が起きているなら、data/movies.json を見ます。
- 送信した値が JSON に追加されているか。
- UUID があるか。
- タイトルが空のデータが保存されていないか。
- 更新した値に書き換わっているか。
- 削除した映画が消えているか。
画面に表示されない場合でも、JSON に保存されているなら、保存処理ではなく表示側を疑います。JSON に保存されていないなら、フォーム送信、入力チェック、保存処理を疑います。
JSON ファイルを手で直して確認したくなることもあります。その場合は、まずコピーを取ってから編集してください。カンマや引用符を一つ消しただけでも JSON として読めなくなり、別のエラーを増やしてしまいます。
ERB のエラーを読む
ERB に文法ミスがあると、画面には 500 が表示されることがあります。
例えば、views/show.erb で <% end %> が足りない、引用符が閉じていない、変数名を間違えた、といった場合です。
このときは、ブラウザの画面だけでなく、ターミナルのエラーメッセージを読みます。エラーには、ファイル名や行番号が含まれていることがあります。
エラーメッセージは最後に読むものではありません。最初に読む事実の一つです。
layout.erb と各 ERB の役割を確認する
画面が二重に崩れているときは、layout.erb と各ビューの役割を確認します。
views/layout.erb は、共通の HTML 構造を持ちます。
<!doctype html>
<html lang="ja">
<head>
...
</head>
<body>
...
<%= yield %>
</body>
</html>
views/index.erb や views/show.erb には、その画面固有の中身だけを書きます。各 ERB に html や body を重ねて書くと、HTML の構造が崩れます。
layout.erb は外枠、各 ERB は中身です。この役割を分けて確認します。
見た目が表示されていても、HTML として確認すべき点は残ります。フォームでは label と入力欄が対応しているか、リンクやボタンの文言だけで行き先や操作が分かるかも確認対象です。
症状ごとに最初に見る場所
よくある症状と、最初に見る場所をまとめます。
| 症状 | 最初に見る場所 |
|---|---|
| フォームを送っても値が届かない | Network タブの Form Data、フォーム部品の name |
| 登録後に増えない | POST /movies のステータス、data/movies.json |
| 更新しても変わらない | Network タブの _method=patch、Sinatra ログ、JSON |
| 削除しても残る | Network タブの _method=delete、Sinatra ログ、JSON |
| 404 になる | URL、映画 ID、JSON 内の ID |
| 500 になる | ターミナルのエラーメッセージ、ERB の行番号 |
| 画面が崩れる | HTML 構造、layout.erb と各 ERB、CSS |
| 入力したタグが動いてしまう | h ヘルパーが外れていないか |
この表は、答えの一覧ではありません。最初に事実を集める場所を選ぶための表です。
よくある失敗を切り分ける
例えば、JSON ファイルを public/ に置いてしまった場合、ブラウザから直接読める場所に保存データを置くことになります。保存場所の問題は、画面ではなくディレクトリ構成を見る必要があります。
POST 後に直接 HTML を返してしまった場合、再読み込みで再送信が起きる可能性があります。これは、Network タブで POST 後に GET へ移っているかを見る必要があります。
紹介文の改行表示を Ruby の gsub("\n", "<br>") で作ると、利用者入力と HTML 生成が混ざります。これは、表示の見た目だけではなく、XSS とエスケープの観点で確認します。
問題の種類によって、見る境界は変わります。
付録のエラー集へ進む
本書の付録には、よくあるエラーをまとめます。
ただし、付録を読む前に、まず自分で次を確認してください。
- どの操作で再現するか。
- Network タブでは何が起きているか。
- Sinatra のログには何が出ているか。
- JSON ファイルはどう変わっているか。
- ERB のエラーメッセージは何を指しているか。
会話やレビューで質問するときも、この情報があると状況を伝えやすくなります。
質問するときは、「再現手順」「期待した結果」「実際の結果」「Network タブで見えたメソッドとステータスコード」「ターミナルに出たログ」を分けて書くと、相手が同じ状況を追いやすくなります。
次の章では、ここで確認した data/movies.json に注目します。JSON ファイルを読んで切り分けられるようになったうえで、ファイル保存にはどのような限界があるのかを考えます。
この章の完成コード
この章では、完成コードに残す変更はありません。第10章までに完成した映画図鑑を使って、問題の切り分け方を学びました。
確認しよう
- 映画を登録し、Network タブ、Sinatra ログ、
data/movies.jsonの 3 つを見比べる。 - 映画を更新し、Network タブの
_method=patchと Sinatra ログの PATCH を見比べる。 - 存在しない映画 ID にアクセスし、Network タブの 404 と JSON 内の ID を見比べる。
views/show.erbを読むだけで、layout.erbと役割が分かれていることを確認する。
考えてみよう
- 画面だけを見て原因を決めると、どのような間違いが起きそうでしょうか。
- JSON に保存されているのに画面に出ない場合、どこを疑えばよいでしょうか。
- 500 が出たとき、なぜまずターミナルのエラーメッセージを見るのでしょうか。
さらに学ぶ
不具合を自力で調べる力を伸ばすには、ブラウザとサーバーのどちらで事実を観察できるかを増やしていきます。
- MDN ブラウザ開発者ツールでは、Network パネルだけでなく、HTML、CSS、JavaScript、コンソールを調べる各ツールの役割を学べます。
- Sinatra 公式ドキュメントでは、開発環境のログ、エラー画面、設定を確認し、サーバー側の問題を切り分ける手掛かりを得られます。