Ruby on rails 使用条件创建嵌套属性

Ruby on rails 使用条件创建嵌套属性,ruby-on-rails,Ruby On Rails,我有三种型号重新进货,产品,和尺寸 #Product has_many :sizes, as: :sizeable #Size belongs_to :sizeable, polymorphic: true 重新进货.rb class Restocking < ApplicationRecord has_many :sizes, as: :sizeable belongs_to :product accepts_nested_attributes_for :siz

我有三种型号重新进货产品,和尺寸

#Product
  has_many :sizes, as: :sizeable 

#Size
  belongs_to :sizeable, polymorphic: true
重新进货.rb

class Restocking < ApplicationRecord
  has_many :sizes, as: :sizeable
  belongs_to :product
  accepts_nested_attributes_for :sizes


  def update_existing_product
    product = self.product
    product.update_attributes(
     price: self.price,
     buying_price: self.buying_price,
    )
    sizes = Size.where(sizeable_id: self.product_id)
    self.sizes.each do |restocking_size|
        sizes.each do |product_size|
          if product_size.size_name == restocking_size.size_name
            product_size.quantity += restocking_size.quantity
            product_size.save
         end
        end
      end
    end
  end

由于循环的构造方式,
Size
被多次创建

代码的修复程序如下所示:

self.sizes.each do |restocking_size|
  if (existing_size = sizes.find{|s| s.size_name == restocking_size.size_name })
    existing_size.tap{|s| s.quantity += restocking_size.quantity }.save!
  else
    # no existing, here goes create
  end
end
但请记住,如果此代码恰好在其他代码更新相同数据的同时运行,则在应用程序级别处理此问题可能会导致竞争条件。 例如:

  • 我们有10件A码B码的
  • 再订5个
  • 代码运行,获取
    大小
    ,我们有10个
    数量
  • 此时,有人购买了一件这种尺寸的物品,剩下9件,这是否会写入db
  • 重新进货继续运行-将5添加到10,将15写入数据库
  • 数量
    为15,其中一项已售出

  • 可以通过在您更新计数器的每个位置使用
    record#with_lock{here update courses}
    来避免(但这会重新加载记录,对于大容量而言可能效率低下)。

    谢谢您添加
    大小。创建
    它会重新创建现有大小。。。如何避免这种情况?@johan在答案中查看代码示例,它不应该(你可以添加日志记录,看看它是否真的找到了现有的大小)我使用了你的代码加上我的
    大小。在
    中创建
    ,否则它将重新创建更新的大小。如果第一个赌注是它没有找到现有的大小,请检查
    大小。查找{…}
    返回记录感谢您使用{u lock{here update accounts}指向
    记录}
    我将检查此项:)
    self.sizes.each do |restocking_size|
      if (existing_size = sizes.find{|s| s.size_name == restocking_size.size_name })
        existing_size.tap{|s| s.quantity += restocking_size.quantity }.save!
      else
        # no existing, here goes create
      end
    end