Rails5.1でform_tagとform_forがform_withに統合されました。
form_withを使ってformを書いたところちょっとした落とし穴があったので共有します。
#問題 : validationエラーがviewに表示されない
例えばこんな感じでviewとcontrollerを書いてると、
validationエラーでsaveできなかった時に:newのviewにエラーが表示されません。
...前略...
<%= form_with model: @user do |f| %>
<!-- createに失敗するとエラー表示 -->
<% if @user.errors.any? %>
<div class="alert alert-danger">
<ul>
<% @user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
...中略...
<% end %>
class EventsController < ApplicationController
# ...中略...
def create
@user = User.new(user_params)
if @event.save
redirect_to @event, notice: '作成しました'
else
render :new
end
end
# ...中略...
end
#原因 : form_withはデフォルトでremote: trueになっている
form操作をAjaxで行い時に、form_tag / form_forだとオプションにremote: trueを指定するだけで対応してくれましたが、
form_withでは何も指定しない場合デフォルトでremote: trueになるようです。
(参考)Ruby on Rails 5.1.2 Module ActionView::Helpers::FormHelper#form_with
#解決策 : form_withのオプションでlocal: trueを指定
form操作をAjaxで処理したいわけでもないなら、
form_withのオプションでlocal: trueを指定することでエラーメッセージをviewに表示できます。
...前略...
<%= form_with model: @user, local: true do |f| %>
<!-- createに失敗するとエラー表示 -->
<% if @user.errors.any? %>
<div class="alert alert-danger">
<ul>
<% @user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
...中略...
<% end %>