はじめに
Railsの学習をProgate(Rails 5)から始めました。その後に自分で環境構築をしたのですが、Rails 7.0にした影響でいろんなところで詰まりました。今回はその中から、アクション内でrenderを使うとエラーになる問題について紹介します。
Rails : 7.0.5
エラーの再現
簡単なTodoアプリを想定します。
タスクが未入力のときに自分で設定したエラーメッセージを表示したいときは、次のようにrender
を使って、アクション内で定義した変数をViewで使用すればいいと思いました。
get "todos/new", to: "todos#new"
post "todos/create", to: "todos#create"
<% if @error_message %>
<%= @error_message %>
<% end %>
<%= form_tag("/todos/create") do %>
<form>
<input type="text" placeholder="タスクを入力する" name="title">
<input type="submit" value="保存する">
</form>
<% end %>
def create
@todo = Todo.new(title: params[:title])
if @todo.save
redirect_to("/todos")
else
@error_message = "タスクを入力してください"
render :new
end
end
しかし次のようなエラーが出てしまいます。
Error: Form responses must redirect to another location
自分で設定したエラーメッセージも表示されません。
must redirect とあるのでもしかすると redirect_to の挙動が変わったのかと思い試してみても、やはり@error_message
は引き継がれませんでした。
解決策
調べた結果、こちら1からのこちら2に行き着き、次のようにstatusを指定すれば想定通りにエラーメッセージを表示することができました。
def create
@todo = Todo.new(title: params[:title])
if @todo.save
redirect_to("/todos")
else
@error_message = "タスクを入力してください"
# status: 422 を追記
render :new, status: 422
end
end
同様にstatusに500
を指定してもメッセージが表示され、コンソール上ではステータスの意味通りのエラーが出ていました。
原因
原因としてはリンク先2にあるように、ステータスにより挙動が違うことがTurboの仕様だから、ということになるようです。Turboがデフォルトで組み込まれたのはRails 7.0以降3なので、statusが必要なのもRails 7.0以降の話なのでしょう。Turboについてよくわかっていませんが…