双嵌套表单不向控制器发送属性

Double nested form not sending attributes to controller

欢迎所有 help/hints/debugging tips/thoughts,因为我在这个问题上已经困了一段时间了。

我有一个 2 级深层嵌套表单。第一级的参数保存正确(例如 options_attributes),但不幸的是最深形式的参数没有被发送到控制器(例如 option_prices_attributes 在我的参数中根本没有显示。我使用 cocoon gem 来创建一个动态嵌套表单。

有趣的是,

(1) 在我的控制台中,我能够创建一个 2 级深度对象,其中还保存了 option_price 参数。

(2) 在 simple_field 表单中使用 :option_prices_attributes 时,它们作为参数发送:

{"utf8"=>"✓", "_method"=>"patch", "authenticity_token"=>"P6oCZkZF8O+, "accommodation_category"=>{"options_attributes"=>{"1568305809712"=>{"name"=>"Option name", "_destroy"=>"false", "option_prices_attributes"=>{"name"=>"Option price", "_destroy"=>"0"}}}}, "commit"=>"Save", "park_id"=>"8", "id"=>"96"}

=> 并因此导致终端中显示一条错误消息 no implicit conversion of Symbol into Integer

我的模特

class AccommodationCategory < ApplicationRecord
  belongs_to :park

  has_many :options, dependent: :destroy
  accepts_nested_attributes_for :options, allow_destroy: true
end


class Option < ApplicationRecord
  belongs_to :accommodation_category

  has_many :option_prices, dependent: :destroy
  accepts_nested_attributes_for :option_prices, allow_destroy: true
end


class OptionPrice < ApplicationRecord
  belongs_to :option
end

Accommodation_categories_controller.rb

class AccommodationCategoriesController < ApplicationController
  # skip_before_action :authenticate_user!

[...]

  def update
    @park = Park.find(params[:park_id])
    @accommodation_category = @park.accommodation_categories.find(params[:id])
    authorize @accommodation_category
    @accommodation_category = @accommodation_category.update_attributes(accommodation_category_params)
  end

  def new_options
    @accommodation_category = AccommodationCategory.find(params[:id])
    @park = @accommodation_category.park
    authorize @accommodation_category
    #2nd level nesting
    # @accommodation_category.options.build
    @accommodation_category.options.each do |option|
      option.option_prices.build
    end
  end

  private
  def accommodation_category_params
    params.require(:accommodation_category).permit(:name, :description, :status, :persons_max, :persons_min, :persons_included, :accommodation_count, :enabled_accommodation_count, :thumb, :included_services, :photo,
      options_attributes: [:name, :description, :_destroy,
        option_prices_attributes: [:name, :price_type, :start_date, :end_date, :price, :duration, :duration_min, :duration_max, :backend_only, :weekend_extra, :_destroy]])
  end
end

views/accommodation_categories/new_options.html.erb

<%= render 'options_new_form', park: @park%>

views/accommodation_categories/options_new_form.html.erb(第一级)

<%= simple_form_for [@park, @accommodation_category] do |f|%>

<h1> <%= @accommodation_category.name %> </h1>

<% @accommodation_category.options.each do |option| %>
  <%= option %>
  <% end %>

<%= f.simple_fields_for :options do |option| %>
<%= render 'option_fields', f: option %>
<% end %>

<div>
  <%= link_to_add_association 'add option', f, :options %>
</div>

<%= f.submit "Save", class: "btn btn-primary" %>
<% end %>

views/accommodation_categories/option_fields.html.erb(二级)


  <%= f.input :name %>
  <%= f.check_box :_destroy %>
  <%= link_to_remove_association "remove option", f %>

<%= f.simple_fields_for :option_prices do |option_price| %>
<%= render 'option_price_fields', f: option_price %>
<% end %>


<%= link_to_add_association 'add option price', f, :option_prices %>

views/accommodation_categories/option_price_fields.html.erb

  <%= f.input :name %>
  <%= f.check_box :_destroy %>
  <%= link_to_remove_association "remove option price", f %>

向控制器发送参数时我的终端中的消息如下:

Processing by AccommodationCategoriesController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"QlROXu9ImP6GSvPJQgd7eVZtaWsiVT6myWzZEFIEtEulSrQmt75XVMEI/avKUzhjZaZG9Kj0Pmih6J/4UYO8IQ==", "accommodation_category"=>{"options_attributes"=>{"1568290804865"=>{"name"=>"option name", "_destroy"=>"false"}}}, "commit"=>"Save", "park_id"=>"8", "id"=>"93"}
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" =  ORDER BY "users"."id" ASC LIMIT   [["id", 1], ["LIMIT", 1]]
  ↳ /Users/xx/.rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
  Park Load (0.4ms)  SELECT  "parks".* FROM "parks" WHERE "parks"."id" =  LIMIT   [["id", 8], ["LIMIT", 1]]
  ↳ app/controllers/accommodation_categories_controller.rb:29
  AccommodationCategory Load (0.2ms)  SELECT  "accommodation_categories".* FROM "accommodation_categories" WHERE "accommodation_categories"."park_id" =  AND "accommodation_categories"."id" =  LIMIT   [["park_id", 8], ["id", 93], ["LIMIT", 1]]
  ↳ app/controllers/accommodation_categories_controller.rb:30
   (0.2ms)  BEGIN
  ↳ app/controllers/accommodation_categories_controller.rb:32
  Option Create (0.3ms)  INSERT INTO "options" ("accommodation_category_id", "name", "created_at", "updated_at") VALUES (, , , ) RETURNING "id"  [["accommodation_category_id", 93], ["name", "option name"], ["created_at", "2019-09-12 12:20:14.265335"], ["updated_at", "2019-09-12 12:20:14.265335"]]
  ↳ app/controllers/accommodation_categories_controller.rb:32
   (0.7ms)  COMMIT
  ↳ app/controllers/accommodation_categories_controller.rb:32
  AccommodationCategory Load (0.2ms)  SELECT  "accommodation_categories".* FROM "accommodation_categories" WHERE "accommodation_categories"."park_id" =  AND "accommodation_categories"."id" =  LIMIT   [["park_id", 8], ["id", 93], ["LIMIT", 1]]
  ↳ app/controllers/accommodation_categories_controller.rb:45
Redirected to http://localhost:3000/accommodation_categories/93/new_discounts
Completed 302 Found in 14ms (ActiveRecord: 2.3ms)

None 的嵌套字段部分似乎有一个包装器-class? Cocoon 明确依赖于特定标记,这可能导致例如嵌套字段似乎已正确插入,但插入到表单之外,当然永远不会发布到 server/controller。