嵌套属性 + multi select:找不到 ID=["1", "2", "3"] 的集合,用于 ID= 的产品?

nested attributes + multi select: Couldn't find Collection with ID=["1", "2", "3"] for Product with ID=?

我与 collections 有一个多对多的关系,是 product

的多select 字段

products_controller.rb

def new
    @product = Product.new
    @product.collections.build
    @product.categories.build
    @product
end

def create
   @product = Product.new(product_params)
   ...
end

private
def product_params
   params.require(:product).permit(:product_id, :name, :price, :popularity, 
        collections_attributes: [ id: [] ])
end

产品型号

class Product < ApplicationRecord
  validates :product_id, uniqueness: true
  has_and_belongs_to_many :collections, optional: true
  accepts_nested_attributes_for :collections, reject_if: ->(attributes){ attributes['id'].blank? }, allow_destroy: true
end

产品浏览

    <%= form.fields_for :collections do |fc| %>
      <%= fc.label :collections %>
      <%= fc.select(:id, Collection.all.collect { |c| [c.name, c.id] }, 
                    { include_blank: true, include_hidden: false }, {multiple: true}) %>
    <% end %>

视图将如下所示,因为用户可以选择 select 多个集合

然而,当我post到/create时,它说

登录 products_params.inspect

不太确定它有什么问题。是因为ids不能取数组吗?如果是这样,有什么解决方案。

如有任何帮助,我们将不胜感激。谢谢!


更新 整个产品形态。请忽略 product_id,因为它不是主键。

<%= form_with(model: product, local: true) do |form| %>
  <% if product.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(product.errors.count, "error") %> prohibited this product from being saved:</h2>

      <ul>
      <% product.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="actions">
    <%= form.label :product_id %>
    <%= form.text_field :product_id %>

   
    <%= form.fields_for :collections do |fc| %>
      <%= fc.label :collections %>
      <%= fc.select(:id, Collection.all.collect { |c| [c.name, c.id] }, 
                    { include_blank: true, include_hidden: false }, {multiple: true}) %>
    <% end %>

    <%= form.submit %>
  </div>
<% end %>

您不需要嵌套属性来关联记录。这是一个极其普遍的误解。事实上,使用 accepts_nested_attributes_for :collections 会导致您更改 collections table 而不是 products_collections 加入 table!

而是使用由 has_and_belongs_to_many :collections 创建的 collection_ids= setter。

class Product < ApplicationRecord
  validates :product_id, uniqueness: true
  # has_and_belongs_to_many is always optional...
  has_and_belongs_to_many :collections
end
<%= form_with(model: product, local: true) do |form| %>
  # ...

  <div class="field">
    <%= form.label :product_id %>
    <%= form.text_field :product_id %>
  </div>
  <div class="field">
    <%= f.label :collection_ids %>
    <%= f.collection_select(:collection_ids, Collection.all, :id, :name, multiple: true) %>
 </div>
 <div class="actions">
    <%= form.submit %>
  </div>
<% end %>
def product_params
   params.require(:product).permit(
     :product_id, :name, :price, :popularity, 
     collection_ids: [] # allows an array of values
   )
end

这将根据数组的内容自动 add/delete 连接行。

accepts_nested_attributes_for 仅当您需要在单个表单提交中传递另一个模型(或连接模型)的属性时才需要。 accepts_nested_attributes_for 实际上不能用于为 has_and_belongs_to_many 关联操作联接 table 行,因为没有模型可以接受嵌套属性。您需要改用 has_many through: