付録D よくあるエラー
この付録では、初学者がつまずきやすい点をまとめます。
エラーが出たときは、まず第11章の考え方に戻ります。画面だけで判断せず、再現手順、Network タブ、Sinatra のログ、JSON ファイル、ERB のエラーメッセージを分けて確認します。
LoadError が出る
LoadError は、必要なファイルや gem を読み込めないときに出ます。
まず確認することは次のとおりです。
bundle installを実行したか。- コマンドに
bundle execを付けているか。 Gemfileに必要な gem が書かれているか。- ファイル名のつづりが合っているか。
本書の起動コマンドは次です。
bundle exec ruby app.rb
ルートが見つからない
存在しない URL にアクセスすると、404 が返ります。
例えば、/movie と /movies は別の URL です。ルート定義とブラウザの URL を見比べます。
get "/movies" do
@movies = load_movies
erb :index
end
/movies/:id のようなルートでは、:id に入る値が data/movies.json の id と一致しているかも確認します。
params のキーが想定と違う
フォームから送信されるキーは、フォーム部品の name 属性で決まります。
<input type="text" name="title">
この場合、Sinatra 側では params["title"] として受け取ります。
値が届かないときは、Network タブの Form Data と、フォーム部品の name を見比べます。id 属性や label の文字ではなく、name 属性を見るのがポイントです。
JSON ファイルが壊れた
data/movies.json は JSON として正しい形でなければ読み込めません。
例えば、カンマや引用符が一つ欠けただけでも壊れます。
[
{
"title": "月面喫茶"
}
]
手で直す場合は、先にコピーを取ります。原因を切り分けている途中で JSON を壊すと、元の問題と別の問題が混ざってしまいます。
404 と 500 を混同する
404 は、指定されたものが見つからないときのレスポンスです。
500 は、サーバー側で例外などが起きたときのレスポンスです。
404 のときは、URL、ルート定義、映画 ID、JSON 内の ID を見ます。500 のときは、ターミナルのエラーメッセージを読みます。ファイル名や行番号が出ていることがあります。
public/ に保存データを置いてしまう
public/ は、ブラウザから直接参照できる静的ファイルを置く場所です。
保存データを public/ に置くと、アプリケーションを通さずにブラウザから読めてしまいます。映画図鑑の保存データは、次の場所に置きます。
data/
movies.json
CSS は public/、保存データは data/ と分けます。
layout.erb と各 ERB の両方に html や body を書く
layout.erb は共通の外枠です。
各ビューには、その画面固有の中身だけを書きます。views/index.erb や views/show.erb に html、head、body を重ねて書くと、HTML の構造が崩れます。
POST 後に HTML を直接返してしまう
登録、更新、削除のあとに HTML を直接返すと、ブラウザの再読み込みで同じ処理が再送信される可能性があります。
本書では、登録、更新、削除のあとにリダイレクトしました。
POST /movies
↓
303 See Other
↓
GET /movies/:id
Network タブで、状態を変えるリクエストのあとに GET へ移っているか確認します。
Network タブを見ずに画面だけで判断する
画面に表示された内容は、結果の一部です。
Web アプリケーションでは、その裏で HTTP リクエストとレスポンスが発生しています。原因を探すときは、Network タブで URL、HTTP メソッド、ステータスコード、Form Data、リダイレクト前後のリクエストを確認します。
紹介文の改行を Ruby で <br> に変換する
紹介文の改行を表示したいからといって、利用者入力へ gsub("\n", "<br>") のような加工をするのは避けます。
表示のために HTML を作る処理と、利用者入力を安全に扱う処理が混ざってしまうためです。
映画図鑑では、CSS の white-space: pre-line; を使って改行を表示しました。
利用者入力をエスケープせず表示する
利用者が入力した値をそのまま HTML として出力すると、XSS の原因になります。
映画図鑑では、表示時に h ヘルパーを使いました。
<%= h(@movie["title"]) %>
入力値を信用するのではなく、出力先の HTML 文脈に合わせてエスケープします。