我创建了一种更新多个记录嵌套属性的方法(感谢railscast和其他帮助),但是在我的模型中,我具有唯一性验证。我允许更新嵌套属性,并且如果更新中包含现有记录空白,则删除它。
我收到以下错误:
ActiveRecord :: RecordInvalid(验证失败:商店产品打印 文件店产品已被拿走):
使用以下内容时:
def update_multiple
@shop_products = ShopProduct.find(params[:shop_product_ids])
@image_files = ImageFile.where(user_id: current_user.id)
@shop_products.reject! do |shop_product|
shop_product.update_attributes!(params[:shop_product].permit(:shop_product, shop_product_print_files_attributes: [ :id, :print_file, :print_location_id, :shop_product_id, :image_file_id ]).reject { |k,v| v.blank? })
end
if @shop_products.empty?
redirect_to '/'
else
@shop_product = ShopProduct.new(params[:shop_product])
render "edit_multiple"
end
end
这种形式:
<%= form_with model: @shop_product, url: update_multiple_shop_products_path, method: :put do |f| %>
<% @shop_products.each do |shop_product| %>
<%= hidden_field_tag "shop_product_ids[]", shop_product.id %>
<% end %>
<%= f.fields_for :shop_product_print_files do |ff| %>
<%= ff.object.print_location.title %>
<%= ff.hidden_field :print_location_id %>
<% if ff.object.image_file_id.present? %>
<%= ff.select :image_file_id, options_for_select(@image_files.map { |image| [image.id, {'data-img-src'=>image.image_file_url(:thumb)}]}, ff.object.image_file_id), {:include_blank => 'Choose None'}, class: "image-picker" %>
<% else %>
<%= ff.select :image_file_id, options_for_select(@image_files.map { |image| [image.id, {'data-img-src'=>image.image_file_url(:thumb)}]}), {:include_blank => 'Choose None'}, class: "image-picker" %>
<% end %>
...
...
...
型号:
class PrintLocation < ApplicationRecord
has_many :shop_products, through: :shop_product_print_files
has_many :shop_product_print_files
end
class ShopProductPrintFile < ApplicationRecord
validates :shop_product, uniqueness: { scope: :print_location }
belongs_to :shop_product
belongs_to :print_location
belongs_to :image_file
end
class ShopProduct < ApplicationRecord
has_many :shop_product_print_files
has_many :print_locations, through: :shop_product_print_files
accepts_nested_attributes_for :shop_product_print_files
accepts_nested_attributes_for :shop_product_print_files, reject_if: :reject_file, :allow_destroy => true
def reject_file(attributes)
if attributes[:image_file_id].blank?
if attributes[:id].present?
attributes.merge!({:_destroy => 1}) && false
else
true
end
end
end
...
end
class ImageFile < ApplicationRecord
# this is where users upload files to
belongs_to :user
has_many :shop_product_print_files
end
路线:
resources :shop_products do
collection do
get :edit_multiple
put :update_multiple
end
end
当我像这样按每条记录进行更新时:
<%= form_for @shop_product do |f| %>
<% PrintLocation.all.each{|p| @shop_product.shop_product_print_files.build(print_location: p) if @shop_product.shop_product_print_files.where(print_location: p).empty? } %>
<%= f.fields_for :shop_product_print_files do |ff| %>
<%= ff.object.print_location.title %>
.....
控制器中的更新方法:
if @shop_product.update!(shop_product_params)
...
使用Update方法可以正常工作。该模型将执行其操作,删除尚未通过但尚未存在的属性,更新已存在的属性,如果不存在则创建新属性。但是,对于update_multiple方法,这似乎并不适用
我只能假设有一些验证回调仅将Update方法列入白名单,但是我不确定吗?
为什么在每条记录的基础上使用Update方法期间,为什么我能够成功更新ShopProduct。但是当我使用实现Update Multiple方法的表单时,会收到验证错误?
是否应适用相同的规则?
这是传递的参数之间的区别
穆特里更新:
参数:{“ utf8” =>“✓”,“ authenticity_token” =>“ ==”,“ shop_product_ids” => [“ 42”],“ shop_product” => {“ shop_product_print_files_attributes” => {“ 0 “ => {” print_location_id“ =>” 1“,” image_file_id“ =>” 2“},” 1“ => {” print_location_id“ =>” 2“,” image_file_id“ =>” 2“},” 2 “ => {” print_location_id“ =>” 3“,” image_file_id“ =>”“},” 3“ => {” print_location_id“ =>” 4“,” image_file_id“ =>”“},” 4“ = > {“ print_location_id” =>“ 5”,“ image_file_id” =>“”},“ 5” => {“ print_location_id” =>“ 6”,“ image_file_id” =>“”}}},“ commit” = >“已检查编辑”}
1条记录更新:
参数:{“ utf8” =>“✓”,“ authenticity_token” =>“ ==”,“ shop_product” => {...“ shop_product_print_files_attributes” => {“ 0” => {“ print_location_id” = >“ 1”,“ image_file_id” =>“ 1”,“ id” =>“ 145”},“ 1” => {“ print_location_id” =>“ 2”,“ image_file_id” =>“”,“ id” =>“ 151”},“ 2” => {“ print_location_id” =>“ 3”,“ image_file_id” =>“”},“ 3” => {“ print_location_id” =>“ 4”,“ image_file_id” = >“”},“ 4” => {“ print_location_id” =>“ 5”,“ image_file_id” =>“”},“ 5” => {“ print_location_id” =>“ 6”,“ image_file_id” =>“ “}},” id“ =>” 42“},” commit“ =>” Sync“,” id“ =>” 42“}
流为:
用户附加/创建ShopProduct的......全部附加后,他们便可以一次更新所有产品。 ShopProduct可以已经附加shop_product_print_files。
然后一次选择要更新的内容...
目标是一次全部更新时,它将覆盖和更新已通过的任何先前记录,或者创建新记录,或者如果未通过则删除现有记录,就像通过记录传递来处理记录一样
>我要注意的是,在一次更新中,我已经拥有了,因此ShopProductPrintFile加载后便会进行更新。但是在multi_update中,它不会被加载并视为新的。因此,验证:validates :shop_product_id, uniqueness: { scope: :print_location_id }
已经存在,不会更新,但是由于验证而“创建”并且不会创建。它是否正确?如果是这样,我如何允许这种情况发生?