Rails Ambassador

form_withまとめ

Rails5.1よりform_withが導入され、form_forやform_tagが非推奨となり今後削除される予定となっています。

form_withの基本構文

一つの構文でフォームが書けるようになりました。

今まではモデルに関連するものは「form_for」、モデルに関連づかないフォームは「form_tag」と使い分けていましたがこれからはform_withで一本化されます。
form_forもform_tagも生成されるformタグは一緒なのでなかなか理解のむずかしいところでもありましたがこれで直感的にformを作成することができるのではないかと思います。
また、デフォルトでremote: :trueの設定になるのが大きな変更点です。
※formのデフォルトのHTTPメソッド(verb)はPOSTです。

関連モデル無(URLを指定する)
<%= form_with url: users_path do |f| %>
  <%= f.text_field :name %>
  <%= f.submit %>
<% end %>
関連モデル有
<%= form_with model: @user do |f| %>
  <%= f.text_field :name %>
  <%= f.submit %>
<% end %>

引数に括弧を使う

引数に括弧がないとダメって方はもちろんできます。

関連モデル無
<%= form_with(url: users_path) do |f| %>
  <%= f.text_field :name %>
  <%= f.submit %>
<% end %>
関連モデル有
<%= form_with(model: @user) do |f| %>
  <%= f.text_field :name %>
  <%= f.submit %>
<% end %>

スコープのprefixを指定する

<%= form_with scope: :session, url: sessions_path do |f| %>
  <%= f.text_field :name %>
  <%= f.submit %>
<% end %>
<form action="/sessions" method="post" data-remote="true">
  <input type="text" name="session[name]">
</form>

form_withにHTMLのclassやidを設定

引数括弧無
<%= form_with model: @user, id: :任意のID, class: :任意のclass do |form| %>
  <%# フォームの部品 %>
<% end %>
引数括弧有
<%= form_with(model: @user, id: :任意のID, class: :任意のclass) do |form| %>
  <%# フォームの部品 %>
<% end %>

今まではhtml: {id: "HOGE" のようにHTML属性を指定していたのが無くなるのは嬉しいですね!

form_withではremote: trueがデフォルトに

form_with で生成されたフォームは、デフォルトで非同期通信XHR(Ajax)リクエストで送信されるようになります。
以前のform_tag と form_for のように、remote: trueの指定をする必要がありません。

viewもerbをレンダリングするのではなくJSで一部書き換えるようにすると非常に読み込みが早いページを簡単に作れますね。

もし以前のようなリモート無効のフォームにしたい場合は local: true を指定してください。(remoteではなくlocalになりますので注意!)

<%= form_with model: @user, local: true do |f| %>
  <%# フォームの部品 %>
<% end %>

以前は「remote: true」で非同期にしていたのが「local: true」で解除されるっていうのは最初ちょっと勘違いするかもしれない部分かもしれません、

form_withではモデル属性に無い入力フォームを追加できる

以下のようにモデル属性には無いhogeを指定することができます。

Userモデルにはhoge属性(カラム)が無い
<%= form_with model: @user, url: users_path do |f| %>
  <%= f.text_field :name %>
  <%= f.text_field :hoge%>
  <%= f.submit %>
<% end %>

以前はモデル属性に無い(テーブルにカラムが無い)入力フォーム(例えばhoge)を作成すると以下のようなエラーとなっていました。

undefined method `hoge' for User

この場合hoge属性(Attribute)を設定する必要がありましたが、form_withでは必要ありません。記述が短くなった分、エラーが出なくなったのでスペルミスなどの間違いに気づきにくくなるかもしれませんね。