Module route in Rails with form_for(@object)

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-11 00:58:41

问题


I have namespaced Controller Entities::Customers

class Entities::CustomersController < ApplicationController
...
end

and namespaced ActiveRecord model:

class Entities::Customer < Entities::User

end

in my routes.rb file i have:

 resources :customers, module: :entities

The module :entities is there because i don't want to have routes such as:

/entities/customers but only:

/customers.

The problem starts when i'm rendering my form:

<%= simple_form_for(@customer) do |f| %>
      <%= f.input :email %>
      <%= f.input :password %>
      <%= f.input :name %>
      <%= f.button :submit %>
<% end %>

This throws error: undefined method `entities_customer_path' for Class..

So the error is that rails think that the correct path is with prefix entities.

Rake routes give me:

             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

回答1:


Ok so after some struggling I've found a solution to this problem:

The simple_form_for(@model) generate route prefixed with entities, since it doesn't know there is scoped path in routes.

So in my _form partial i had to manually tell rails which route to use depending on action_name helper method in my partial.

<%
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 %>



回答2:


A global solution for all project can be overriding ApplicationHelper method form_with (currently in Rails 5):

in 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

So that, in case to have routes like

 scope module: 'site' do
  resources :translations
 end

you can code in your _form.html.erb:

<%= form_with(model: @translation, method: :patch) do |form| %>

without errors



来源:https://stackoverflow.com/questions/37556575/module-route-in-rails-with-form-forobject

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!