namespaceでnestされたcontroller(Admin::Userなど)のアクション宛てformを
form_with
で記述したい場合の雛形になります。
書き方
◆ new → create
new.html.erbのviewからAdmin::UsersController
のcreate
アクションへ送りたい場合、htmlレベルでは
<form action="/admin/users" method="post" >
<input type="text" name="user[name]">
</form>
こうなっていてほしいが、form_withではどう記述すればよいか?
① model: を使う方法
model:
で@userを指定し、url:
でpathを指定します。
<%= form_with model: @user, url: admin_users_path, local: true do |f| %>
<%= f.text_field :name %>
<% end %>
② model: を使わない方法
scope:
で:user
を指定し、 url:
でpathを指定します。
scope: :user
によってパラメーターのuser[]
を生成するようです。
<%= form_with scope: :user, url: admin_users_path, local: true do |f| %>
<%= f.text_field :name %>
<% end %>
(ちなみに、scope: :user
をなくすと)
<%= form_with url: admin_users_path, local: true do |f| %>
<%= f.text_field :name %>
<% end %>
↓htmlレベルでは
<form action="/admin/users" method="post" >
<input type="text" name="name">
</form>
user[name]
ではなく、name
になっています。
◆ edit → update
同様に、edit.html.erbからAdmin::UsersController
のupdate
アクションへ送りたい場合、htmlレベルでは
<form action="/admin/users/3" method="post"><input type="hidden" name="_method" value="patch" />
<input type="text" name="user[name]">
</form>
こんな感じになっていてほしいが、form_withではどう記述すればよいか?
① model: を使う方法
model:
で@userを指定し、url:
でpathを指定します。
<%= form_with model: @user, url: admin_user_path, local: true do |f| %>
<%= f.text_field :name %>
<% end %>
② model: を使わない方法
scope:
で:user
を指定し、 url:
でpath、method:
で:patch
を指定します。
<%= form_with scope: :user, url: admin_user_path, method: :patch, local: true do |f| %>
<%= f.text_field :name %>
<% end %>
(ちなみに、method: :patch
をなくすと)
<%= form_with scope: :user, url: admin_user_path, local: true do |f| %>
<%= f.text_field :name %>
<% end %>
↓htmlレベルでは
<form action="/admin/users/3" method="post">
<input type="text" name="user[name]">
</form>
<input type="hidden" name="_method" value="patch" />
が無くなりました。
これにより「htmlメソッドはpatchという体裁で送っているよ」というメッセージが消えたので、railsサーバーはPOSTが届いたと認識します。(詳しくはこちら)
methodがPOST、pathがadmin_user_pathの組み合わせは存在しないので、Routing Errorになるはずです。
結論
form_withではmodel:
を使えば空気を読んで自動翻訳くれるのでかなり楽。
しかし、nestされている状態とpathまでは空気読みきれないので、mode:
とurl:
のセットを使えばOK.