【问题标题】:nested attributes + multi select: Couldn't find Collection with ID=["1", "2", "3"] for Product with ID=?嵌套属性 + 多选:对于 ID = 的产品,找不到 ID = [“1”、“2”、“3”] 的集合?
【发布时间】:2021-04-28 13:36:01
【问题描述】:

我与collections 有多对多关系是product 的多选字段

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

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

但是,当我发帖到 /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 %>

【问题讨论】:

  • 你能展示整个表格吗?您只显示了其中的一部分
  • @Joel_Blum 不用担心。刚刚更新
  • 您确定 form_with 正在获取新产品的实例吗?
  • @Joel_Blum,是的。在 new.html 我有&lt;%= render 'form', product: @product %&gt;。我在帖子中包含了控制器的新方法。
  • @AustinP 我可能错了,但不应该是这样吗? params.require(:product).permit(:product_id, :name, :price, :popularity, collections_attributes: [ :id ])

标签: ruby-on-rails ruby activerecord


【解决方案1】:

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

只需使用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

这将根据数组的内容自动添加/删除连接行。

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

【讨论】:

  • > accept_nested_attributes_for 仅当您需要在单个表单提交中传递另一个模型(或连接模型)的属性时才需要。但这正是他不想做的事?
  • 谢谢,我真的不知道accepts_nested_attributes_for的用途。因此,据我了解,它的唯一用例是使用相同的表单修改另一个表。
  • @Joel_Blum 请注意,我编写了连接模​​型 - 不是连接表。只有当您需要传递某种描述关系的附加数据时,它才真正相关。如果您只是在 C 上链接 A 和 B,那么不会。
猜你喜欢
  • 1970-01-01
  • 2021-01-17
  • 2023-03-16
  • 1970-01-01
  • 2019-05-11
  • 1970-01-01
  • 2021-12-28
  • 2023-03-05
相关资源
最近更新 更多