我的情况:
我有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
。
我很困惑的是可以在create方法中检查它吗?
到目前为止,我发现了这种rails方法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
答案 0 :(得分:0)
答案 1 :(得分:0)
从此更改您的create
操作代码
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
对此
def create
@sale_item = SaleItem.find_or_create_by(sale_item_params) do |sale_item|
sale_item.quantity = sale_item.quantity.to_i + sale_item_params[:quantity].to_i
sale_item.save
end
@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
find_or_create_by(sale_item_params)
首先将找到带有sale_id
,product_id
和quantity
的sale_item,然后如果找不到任何sale_item记录,它将创建一个新记录。两种情况下,您都可以更新数量。
答案 2 :(得分:0)
我认为您必须定义唯一键才能找到SaleItem
sale_id
和product_id
是查找SaleItem
的键。SaleItem
方法上查找或创建create
。控制器示例:
class SaleItemsController < ApplicationController
before_action :initialize_sale_item, only: [:create]
def create
@sale_item.assign_attributes(sale_item_params)
@sale_item.save
# render or respond_to ...
end
private
def sale_item_params
params.require(:sale_item).permit(:sale_id, :product_id, :quantity)
end
def sale_item_key_params
params.require(:sale_item).permit(:sale_id, :product_id)
end
def initialize_sale_item
@sale_item = SaleItem.find_or_initialize_by(sale_item_key_params)
end
end
Talha Junaid
的建议,您可以使用find_or_create_by
代替find_or_initialize_by
(并删除initialize_sale_item
...)