Мой сценарий:
У меня есть SaleItem
модель, в которой хранится (:sale_id, :product_id, :quantity, :total_price)
.
class SaleItem < ApplicationRecord
belongs_to :sale
belongs_to :product
before_save :set_unit_price
before_save :set_total_price
before_save :set_total_disscounted_price
def unit_price
if persisted?
self[:unit_price]
else
product.price_pence
end
end
def total_price
unit_price * quantity
end
private
def set_unit_price
self[:unit_price] = unit_price
end
def set_total_price
self[:total_price] = quantity * set_unit_price
end
def set_total_disscounted_price
self[:total_disscounted_price] =self[:total_price] - (self[:total_price] * self.sale.event.event_disscount) / 100
end
end
Моя проблема в том, что всякий раз, когда я создаю новый объект SaleItem
, я хочу проверить, существует ли такая же запись, и если это так, то мне просто нужно сложить :quantity
и пересчитать общую стоимость (в модели) в соответствии с на новый :quantity
.
Что меня смущает, можно ли проверить это в методе создания?
До сих пор я нашел этот метод рельсов first_or_create
.
Это мой исходный код от SaleItem
контроллера
class SaleItemsController < ApplicationController
def create
@sale = @sale_item.sale
@sale_item = SaleItem.create(sale_item_params)
@event = @sale.event
if @sale_item.save
redirect_to event_sale_path(@event, @sale)
else
redirect_to event_sale_path(@event, @sale)
end
end
private
def sale_item_params
params.require(:sale_item).permit(:sale_id, :product_id, :quantity)
end
end
и затем после того, как я нашел first_or_create
, я начал менять его на это, но еще не закончил, так как немного застрял:
class SaleItemsController < ApplicationController
def create
@sale_item = SaleItem.where(sale_id: params[:sale_id], product_id: sale_item_params[:product_id]).first_or_create do |sale_item|
sale_item.quantity = sale_item.quantity.to_i + sale_item_params[:quantity].to_i
end
@sale = @sale_item.sale
@sale_item = SaleItem.create(sale_item_params)
@event = @sale.event
if @sale_item.save
redirect_to event_sale_path(@event, @sale)
else
redirect_to event_sale_path(@event, @sale)
end
end
private
def sale_item_params
params.require(:sale_item).permit(:sale_id, :product_id, :quantity)
end
end
Я не мог понять, как обновить найденную запись и не изменять вновь созданную запись, поэтому я создал переменную @new_record
и первоначально установил ее на false
, а затем после создания новой записи, @new_record
изменяется на true
. Таким образом, я мог отслеживать каждую запись и изменять ее при необходимости.
Это SaleItem Controller
обновленный код
class SaleItemsController < ApplicationController
def create
@new_record = false
@sale_item = SaleItem.where(sale_id: params[:sale_id], product_id: sale_item_params[:product_id]).first_or_create do |sale_item|
sale_item.quantity = sale_item_params[:quantity]
@new_record = true
end
@new_record == false ? @sale_item.quantity = @sale_item.quantity.to_i + sale_item_params[:quantity].to_i : sale_item_params[:quantity].to_i
@sale = @sale_item.sale
@event = @sale.event
if @sale_item.save
redirect_to event_sale_path(@event, @sale)
else
redirect_to event_sale_path(@event, @sale)
end
end
def destroy
@sale_item = SaleItem.find(params[:id])
@sale = @sale_item.sale
@event = @sale.event
@sale_item.destroy
redirect_to event_sale_path(@event, @sale)
end
private
def sale_item_params
params.require(:sale_item).permit(:sale_id, :product_id, :quantity)
end
end