TL;DR
以下のようにurlを直接指定しなくても
<%= form_with model: @user, url: admin_users_path, local: true do |f| %>
こうやって簡潔に書けるよ
<%= form_with model: [:admin, @user], local: true do |f| %>
前提
環境
- Rubyのバージョン: 2.5.1
- Railsのバージョン: 5.2.0
フォルダ構成
- app/
- controllers/
- admin/
- users_controller.rb
- admin/
- models/
- user.rb
- views/
- admin/
- users/
- new.html.erb
- users/
- admin/
- controllers/
各ファイル概要
# users_controller.rb
class Admin::UsersController < ApplicationController
def new
@user = User.new
end
def create
@user = User.new(user_params)
@user.save!
end
private
def user_params
params.require(:user).permit(:name, :age)
end
end
<!-- new.html.erb -->
<%= form_with model: [:admin, @user], local: true do |f| %>
<%= f.text_field :name %>
<%= f.text_field :age %>
<%= f.submit %>
<% end %>
ポイント
form_withの引数に[:admin, @user]
を渡すことです。
こうすることで,/admin/users
というurlをRailsが生成してくれます。
これまで私はこの方法を知らず,urlオプションにヘルパーを直接指定していました。
<!-- new.html.erb -->
<%= form_with model: @user, url: admin_users_path, local: true do |f| %>
<%= f.text_field :name %>
<%= f.text_field :age %>
<%= f.submit %>
<% end %>
冗長ですね。何度かこの方法で実装した後に,もう少しスマートにかけるのでは?と思いform_withのコードを読んだところ,しっかりコメントしてありました。
# For namespaced routes, like +admin_post_url+:
#
# <%= form_with(model: [ :admin, @post ]) do |form| %>
# ...
# <% end %>
冗長だなーって思ったときは,きっとより良い書き方をRailsが用意してくれているはずなので,コードを見にいったり,公式ドキュメントを読んだりするのは大切ですね。
まとめ
- コントローラの名前空間をわけたときは,form_withのキーワード引数(
model:
)に配列を指定すると,いい感じにurlを解決してくれます - コードを書いていて違和感を覚えたら,もっといい書き方がないか調べてみると良いかもしれません
- (これはまとめというか自戒です)