检查创建动作中是否存在记录

时间:2018-10-31 14:32:47

标签: ruby-on-rails ruby ruby-on-rails-5

我的情况:

我有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

3 个答案:

答案 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_idproduct_idquantity的sale_item,然后如果找不到任何sale_item记录,它将创建一个新记录。两种情况下,您都可以更新数量。

答案 2 :(得分:0)

我认为您必须定义唯一键才能找到SaleItem

  • 例如,如果sale_idproduct_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
相关问题