【Rails】errors_messageが出力されない時の対処法

プログラミング,Ruby on Rails

Ruby on Railsを使っていて, バリデーションチェックでエラーになったのにエラーメッセージが表示されないときの対処法です。

# version
ruby 3.1.2p20
Rails 7.0.4

結論:status: :unprocessable_entityを付ける

修正前のコントローラはこんな感じ

def create
  if @book.valid?
    @book.save!
    redirect_to book_path
  else
    render :new
  end
end

それから, ビュー

<%= form_with @book do |form| %>
  <% @book.errors.full_messages.each do |msg| %>
    <%= msg %>
  <% end %>
  <%= form .......%> # 省略
<% end %>

この状態でsubmitしてバリデーションエラーになり, newビューがレンダリングされたのに, バリデーションエラーメッセージが出力されない。

Ralis7の場合, renderに`status: :unprocessable_entity`を付けると良い。

修正後のコントローラ

def create
  if @book.valid?
    @book.save!
    redirect_to book_path
  else
    render :new, status: :unprocessable_entity
  end
end

ここからは「いや、それ何?」って方へ向けた記事

`status: :unprocessable_entity`って何よ?って思ったので調べてみました。

上記構文はHTTPステータス=422を返しますという意味です。
422って何だっけ?って方はこちら

422はサーバ側がリクエストを理解しているのに, ユーザ側の問題で処理できないケース
すなわちRailsでは, バリデーションエラーのときに返却するコードです。

分かったけど, 今まで書かなくて良かったんじゃない?

そう思われた方はその通りですが, Rails7ではフロントエンド技術としてTurboが標準でインストールされ, サーバ側にPOSTリクエストが行われた場合, Turboは新しいビューに303リダイレクトされることを想定しています。

参考1:Turbo Handbook
参考2:Rails pull request #41026

つまり, バリデーションエラーとなったので, レンダリングする際に「422を返却しますよ」と明示する必要があるということです。

今日はここまでです!