Rails 中的模块路由 form_for(@object)
Module route in Rails with form_for(@object)
我有命名空间控制器Entities::Customers
class Entities::CustomersController < ApplicationController
...
end
和命名空间 ActiveRecord 模型:
class Entities::Customer < Entities::User
end
在我的 routes.rb 文件中我有:
resources :customers, module: :entities
模块 :entities 在那里,因为我不想有这样的路线:
/entities/customers 但只有:
/客户.
当我呈现我的表单时问题开始了:
<%= simple_form_for(@customer) do |f| %>
<%= f.input :email %>
<%= f.input :password %>
<%= f.input :name %>
<%= f.button :submit %>
<% end %>
这会抛出错误:Class..
的未定义方法“entities_customer_path”
所以错误是 rails 认为正确的路径是带有前缀实体。
佣金路线给我:
Prefix Verb URI Pattern Controller#Action
customers GET /customers(.:format) entities/customers#index
POST /customers(.:format) entities/customers#create
new_customer GET /customers/new(.:format) entities/customers#new
edit_customer GET /customers/:id/edit(.:format) entities/customers#edit
customer GET /customers/:id(.:format) entities/customers#show
PATCH /customers/:id(.:format) entities/customers#update
PUT /customers/:id(.:format) entities/customers#update
DELETE /customers/:id(.:format) entities/customers#destroy
好的,经过一番努力,我找到了解决这个问题的方法:
simple_form_for(@model) 生成以实体为前缀的路由,因为它不知道路由中有作用域路径。
所以在我的 _form
部分中,我不得不手动告诉 rails 使用哪条路线,具体取决于我部分中的 action_name
辅助方法。
<%
case action_name
when 'new', 'create'
action = send("customers_path")
method = :post
when 'edit', 'update'
action = send("customer_path", @customer)
method = :put
end
%>
<%= simple_form_for(@customer, url: action, method: method) do |f| %>
<%= f.input :email %>
<%= f.input :password %>
<%= f.input :name %>
<%= f.button :submit %>
<% end %>
所有项目的全局解决方案可以覆盖 ApplicationHelper
方法 form_with
(目前在 Rails 5):
在aplication_helper.rb
def form_with(**options)
if options[:model]
class_name = options[:model].class.name.demodulize.underscore
create_route_name = class_name.pluralize
options[:scope] = class_name
options[:url] = if options[:model].new_record?
send("#{create_route_name}_path")
# form action = "customers_path"
else
send("#{class_name}_path", options[:model])
# form action = "customer/45"
end
# post for create and patch for update:
options[:method] = :patch if options[:model].persisted?
options[:model] = nil
super
end
end
这样,如果有像
这样的路线
scope module: 'site' do
resources :translations
end
您可以在 _form.html.erb 中编码:
<%= form_with(model: @translation, method: :patch) do |form| %>
没有错误
我有命名空间控制器Entities::Customers
class Entities::CustomersController < ApplicationController
...
end
和命名空间 ActiveRecord 模型:
class Entities::Customer < Entities::User
end
在我的 routes.rb 文件中我有:
resources :customers, module: :entities
模块 :entities 在那里,因为我不想有这样的路线:
/entities/customers 但只有:
/客户.
当我呈现我的表单时问题开始了:
<%= simple_form_for(@customer) do |f| %>
<%= f.input :email %>
<%= f.input :password %>
<%= f.input :name %>
<%= f.button :submit %>
<% end %>
这会抛出错误:Class..
的未定义方法“entities_customer_path”所以错误是 rails 认为正确的路径是带有前缀实体。
佣金路线给我:
Prefix Verb URI Pattern Controller#Action
customers GET /customers(.:format) entities/customers#index
POST /customers(.:format) entities/customers#create
new_customer GET /customers/new(.:format) entities/customers#new
edit_customer GET /customers/:id/edit(.:format) entities/customers#edit
customer GET /customers/:id(.:format) entities/customers#show
PATCH /customers/:id(.:format) entities/customers#update
PUT /customers/:id(.:format) entities/customers#update
DELETE /customers/:id(.:format) entities/customers#destroy
好的,经过一番努力,我找到了解决这个问题的方法:
simple_form_for(@model) 生成以实体为前缀的路由,因为它不知道路由中有作用域路径。
所以在我的 _form
部分中,我不得不手动告诉 rails 使用哪条路线,具体取决于我部分中的 action_name
辅助方法。
<%
case action_name
when 'new', 'create'
action = send("customers_path")
method = :post
when 'edit', 'update'
action = send("customer_path", @customer)
method = :put
end
%>
<%= simple_form_for(@customer, url: action, method: method) do |f| %>
<%= f.input :email %>
<%= f.input :password %>
<%= f.input :name %>
<%= f.button :submit %>
<% end %>
所有项目的全局解决方案可以覆盖 ApplicationHelper
方法 form_with
(目前在 Rails 5):
在aplication_helper.rb
def form_with(**options)
if options[:model]
class_name = options[:model].class.name.demodulize.underscore
create_route_name = class_name.pluralize
options[:scope] = class_name
options[:url] = if options[:model].new_record?
send("#{create_route_name}_path")
# form action = "customers_path"
else
send("#{class_name}_path", options[:model])
# form action = "customer/45"
end
# post for create and patch for update:
options[:method] = :patch if options[:model].persisted?
options[:model] = nil
super
end
end
这样,如果有像
这样的路线 scope module: 'site' do
resources :translations
end
您可以在 _form.html.erb 中编码:
<%= form_with(model: @translation, method: :patch) do |form| %>
没有错误