Rails 4:复杂表单和嵌套属性

时间:2016-02-03 19:13:30

标签: ruby-on-rails forms routing nested-forms nested-attributes

我有一个Rails 4应用程序,其中有两个相关的控制器,potential_clientlocation。我试图通过位置控制器创建潜在客户端。我相信我的表单有问题,因为它作为PATCH提交到该位置,而不是按如下方式创建新的potential_client:

class Location < ActiveRecord::Base
    validates_presence_of :name, :email, :address, :phone
    has_many :potential_clients
    accepts_nested_attributes_for :potential_clients
end

class PotentialClient < ActiveRecord::Base
    validates_presence_of :name, :email, :phone
    belongs_to :location
end

我的路线配置如下:

resources :locations do
    resources :potential_clients
end

并在我的 app / views / locations / show.html.erb 中,我有以下表格:

<div class="form-container">
    <%= form_for @location do |f| %>
        <%= f.fields_for :potential_client do |pc_form| %>

            <%= pc_form.label :name %>
            <%= pc_form.text_field :name %><br />

            <%= pc_form.label :email %>
            <%= pc_form.email_field :email %><br />

            <%= pc_form.label :phone %>
            <%= pc_form.number_field :phone %><br />

            <%= pc_form.label :message %>
            <%= pc_form.text_field :message %><br />


            <%= pc_form.hidden_field :location_id, :value => @location.id %>

            <%= pc_form.submit "Submit" %>

        <% end %>
    <% end %>
</div>

表单正确加载,但是当我尝试提交某些内容时,我在我的控制台中出现Unpermitted parameter: potential_client错误,但在location_controller我有:

def location_params
    params.require(:location).permit(:name, :email, :address, :phone, :potential_client, potential_client_attributes: [:name, :email, :message, :phone])
end

...最重要的是,当我尝试创建一个potential_client时,我的控制台说:

Started PATCH "/locations/1" for ::1 at 2016-02-03 13:18:27 -0500
ActiveRecord::SchemaMigration Load (0.1ms)  SELECT "schema_migrations".* FROM "schema_migrations"
Processing by LocationsController#update as HTML

所有路线如果有帮助:

location_potential_clients     GET    /locations/:location_id/potential_clients(.:format)          potential_clients#index
                               POST   /locations/:location_id/potential_clients(.:format)          potential_clients#create
 new_location_potential_client GET    /locations/:location_id/potential_clients/new(.:format)      potential_clients#new
edit_location_potential_client GET    /locations/:location_id/potential_clients/:id/edit(.:format) potential_clients#edit
     location_potential_client GET    /locations/:location_id/potential_clients/:id(.:format)      potential_clients#show
                               PATCH  /locations/:location_id/potential_clients/:id(.:format)      potential_clients#update
                               PUT    /locations/:location_id/potential_clients/:id(.:format)      potential_clients#update
                               DELETE /locations/:location_id/potential_clients/:id(.:format)      potential_clients#destroy
                     locations GET    /locations(.:format)                                         locations#index
                               POST   /locations(.:format)                                         locations#create
                  new_location GET    /locations/new(.:format)                                     locations#new
                 edit_location GET    /locations/:id/edit(.:format)                                locations#edit
                      location GET    /locations/:id(.:format)                                     locations#show
                               PATCH  /locations/:id(.:format)                                     locations#update
                               PUT    /locations/:id(.:format)                                     locations#update
                               DELETE /locations/:id(.:format)                                     locations#destroy

或许是因为:location_id:id对于两个路由都是相同的,而Rails路由到位置而不是potential_client

1 个答案:

答案 0 :(得分:3)

为什么要补丁?

当你这样做时:

<%= form_for @location do |f| %>

rails多态路由助手查看@location并使用@location.new_record?查看是否应该路由到updatecreate

因此,在您的locations#show操作中,您传递的是持久记录 - 因此它会路由到update

如果您想要一个仅发布潜在客户的单独表单,您可以这样做:

<%= form_for [@location, @potential_client] do |f| %>

如果是新记录,则会创建POST locations/1/potential_clients请求;如果已保留,则会PATCH locations/1/potential_clients/1

嵌套属性

它是一个简单的复数错误。您的表单accepts_nested_attributes_for :potential_clients,而您的表单有<%= f.fields_for :potential_client do |pc_form| %>

使用fields_for时,应使用与关系相同的名称 - 因此,对于has_many,它应为复数形式。

<div class="form-container">
    <%= form_for @location do |f| %>
        <%= f.fields_for :potential_clients do |pc_form| %>
            # ...
        <% end %>
    <% end %>
</div>

请注意,正确的参数密钥为potential_clients_attributes,因此您应将白名单列入白名单。

def location_params
    params.require(:location)
          .permit(
            :name, :email, :address, :phone, 
            potential_clients_attributes: [:name, :email, :message, :phone]
          )
end