создавать вложенные атрибуты с условиями - PullRequest
0 голосов
/ 23 февраля 2019

У меня есть три модели Пополнение запасов , Продукт и Размер

#Product
  has_many :sizes, as: :sizeable 

#Size
  belongs_to :sizeable, polymorphic: true

restocking.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

Таким образом, метод update_existing_product обновляет цены и количество существующих размеров ...

Если найден аналогичный size_name, он обновляет существующее количество размеров, в противном случае он создает новый ... Я неНе удается правильно создать новые размеры ...

Я должен использовать этот метод Size.create, но когда я помещаю его в цикл, он создает один и тот же размер много раз.

Size.create!(
    sizeable_id: self.product_id,
    sizeable_type: "Product",
    size_name: restocking_size.size_name,
    quantity: restocking_size.quantity,
)

1 Ответ

0 голосов
/ 23 февраля 2019

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

Но имейте в виду, что обработка этогона уровне приложения может привести к состязанию, если этот код запускается в то же время, когда какой-либо другой код обновляет те же данные.Например:

  1. у нас есть 10 элементов размером A элемента B
  2. , восстанавливающих еще 5
  3. код, выполняется, выборки sizes, там у нас 10 вquantity
  4. в этот момент кто-то покупает один предмет такого размера, осталось 9 предметов, и записывается ли это в дБ
  5. продолжается пополнение запасов - прибавляет 5 к 10, пишет 15 в дБ
  6. quantity равен 15, тогда как один предмет был продан

Этого можно избежать, используя record#with_lock{ here update happens } в каждом месте, где вы обновляете счетчик (но это перезагружает запись, может бытьнеэффективно для больших объемов).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...