Rails创建连接表对象在特殊情况下不应该创建而应该更新



在网上商店我有一个预订,需要知道预订是否已经存在于订单。我把整个东西都修好了,但后来的细节…

…现在'预订产品'(或者在正常英语中:将产品添加到您的购物车中)在每种情况下都会在订单列表中添加一个全新的预订。当这个产品已经订过一次的时候不应该,那么只需要改变数量。

很简单,对吧?只要一个简单的if语句,整个过程就可以了。

bookings_controller.rb

  def create
    @order = current_order
    # If product has already been booked
    if @order.bookings.where(product_id: params[:product_id]).exists?
      # Then: Only alter the quantity in the booking.
      @booking = @order.bookings.where(product_id: params[:product_id])
      @booking.product_quantity = params[:product_quantity]
    else
      # Else: Make a new booking.
      @booking = @order.bookings.new(booking_params)
      @product = @booking.product
      @booking.product_name = @product.name
      @booking.product_price = @product.price
    end
    @order.sum_all_bookings 
    @order.save
  end
  # ...
  def booking_params
    params.require(:booking).permit(:product_quantity, :product_id)
  end

似乎不起作用。

如何在if语句中进行检查?或者我应该走一条完全不同的路线来更新预订?

编辑

我已经尝试了各种组合在这个形状之后的gmcnaughton答案。我要么仍然得到多个元素,要么根本没有元素。这个没有给我任何条目。

bookings_controller.rb

  def create
    @order = current_order
    @booking = @order.bookings.find_or_create_by(product_id: params[:product_id])
    product = @booking.product
    if @booking.new_record?
      @booking.product_name = product.name
      @booking.product_price = product.price
    else
    @booking.product_quantity = params[:product_quantity]
    @booking.save
    @order.sum_all_bookings 
    @order.save
  end

我是否也应该控制预订id ?但这没有意义,因为在查找现有预订的情况下,它应该已经在那里了。

也许我是通过remote: true form解除预订的?

编辑2

也不工作:

bookings_controller.rb

  def create
    @order = current_order
    @booking = @order.bookings.where(product_id: params[:product_id]).first_or_initialize
    if @booking.new_record?
      @booking.product_id = params[:product_id]
      product = @booking.product
      @booking.product_name = product.name
      @booking.product_price = product.price
    else
    @booking.product_quantity = params[:product_quantity]
    @booking.save
    @order.sum_all_bookings 
    @order.save
  end

编辑3

也许这与它有关:

categories_controller。rb/Shop

def index
    @categories = Category.all.order(name: :asc)
    # Voor het inzien van wat al geselecteerd is.
    @order = current_order
    # Voor het aanslaan van een nieuwe booking.
    @booking = current_order.bookings.new
  end

它基本上列出了整个初始商店。@booking用于构建每个产品的表单。

以下工作:

  def create
    @booking = @order.bookings.find_by(product_id: params[:booking][:product_id])
    if @booking
      @booking.product_quantity = params[:booking][:product_quantity]
      @booking.save
    else
      @booking = @order.bookings.new(booking_params)
      @product = @booking.product
      @booking.product_name = @product.name
      @booking.product_price = @product.price
    end
    @order.save
  end

显然我需要抓住参数,通过添加[:booking]像在params[:booking][:product_id]。有人知道为什么吗?

这个想法是对的,但我认为你错过了一个呼叫.first:

@booking = @order.bookings.where(product_id: params[:product_id])
  => #<ActiveRecord::Relation>
应:

@booking = @order.bookings.where(product_id: params[:product_id]).first
  => #<Booking>

…否则你是在更新关系,而不是Booking模型。您可能还想在修改@booking.save之后调用它。

单独,ActiveRecord也有first_or_initializefirst_or_create助手,让您找到一个匹配的实例或构建/创建一个新的:

@booking = @order.bookings.where(product_id: params[:product_id]).first_or_initialize
if @booking.new_record?
  @product = @booking.product
  ...other stuff for new record...
else
  @booking.product_quantity = params[:product_quantity]
end
@booking.save

最新更新