update_attributes!()验证在自定义更新上失败,但可用于常规更新

时间:2019-07-20 01:49:17

标签: ruby-on-rails ruby

我创建了一种更新多个记录嵌套属性的方法(感谢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 }已经存在,不会更新,但是由于验证而“创建”并且不会创建。它是否正确?如果是这样,我如何允许这种情况发生?

0 个答案:

没有答案