form_withとは
Railsアプリケーションでformを作成する時にform_for/form_tagを使っていました。
任意のmodelに紐づくフォームを作成したい場合にはform_forを使い、modelに紐づかない場合にはform_withを使います。
form_forを使えばPOSTの送信先urlなどを全て自動で行いますが、form_forの場合は全て明示します。
HTMLタグのヘルパーのようなイメージで使います。
【Rails】form_for/form_tagの違い・使い分けをまとめた
しかし、Rails5.1
以降は2つのメソッドを統合したform_withが登場し、form_withの利用が推奨されています。
form_withでページが更新されない
form_withを使ってユーザのログインフォームを作っていました。
form_withにはUserModel
を紐づけており、バリデーションやログイン認証の結果にエラーがあれば、viewに反映せるようにしていました。
<%= form_with model: @user, url: user_path do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name %>
<%= f.text_field :user_name, class: "form-control" %>
<%= f.label :email %>
<%= f.email_field :email, class: "form-control" %>
<%= f.label :password %>
<%= f.password_field :password, class: "form-control" %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation, class: "form-control" %>
<%= f.submit yield(:btn_text), class: "btn btn-primary" %>
<% end %>
ところが、エラーは発生しているのにviewには反映されない問題に衝突しました。
これは、form_withでのパラメータの送信はajaxで行われている
ためです。
HTMLのフォームとしてPOSTしたい場合はlocal: true
オプションを付け加えます。
<%= form_with model: @user, url: user_path, local: true do |f| %>
:
<% end %>
これでバリデーションなどのエラー結果を表示するviewを表示できます。
都度フォームにオプションをつけるのが面倒な場合は、config/initialize
ディレクトリに適当なファイルを作成し以下のコードを追記します。
Rails.application.configure do
config.action_view.form_with_generates_remote_forms = false
end