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.