Rails首先或初始化不起作用

时间:2016-10-12 11:41:16

标签: ruby-on-rails jointable

我有一个产品 我有一个订单 我在两者之间预订。

每当我从产品到订单进行预订时,它都会保存一个新的唯一预订。

它应该:

  1. 在第一次使用此产品制作时保存新的预订。
  2. 如果产品已预订一次,请不要进行新的预订,但要查找并覆盖旧的预订。
  3. 如果产品已在订单上预订,但未进行任何更改,则不会进行任何数据库事务。
  4.   def create
        @order = current_order
        @booking = @order.bookings.where(product_id: params[:product_id]).first_or_initialize
        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
    

    不起作用。

    以下工作:

      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]来获取参数。谁知道为什么?

2 个答案:

答案 0 :(得分:0)

你可以尝试

  @order.bookings.find_or_initialize_by(product_id: params[:product_id]).tap do |b|
        # your business logic here
  end

答案 1 :(得分:0)

为避免重复,您应该正确设置关系并使用数据库索引来确保唯一性。

class Order
  has_many :bookings
  has_many :products, though: :bookings
end

class Booking
  belongs_to :order
  belongs_to :product
  validates_uniqueness_of :order_id, scope: :product_id
end

class Product
  has_many :bookings
  has_many :orders, though: :bookings
end

此处的验证将阻止在应用程序级别插入重复项。但是它仍然容易出现竞争条件。

class AddUniquenessContstraintToBooking < ActiveRecord::Migration[5.0]
  def change
    add_index :bookings, [:order_id, :product_id], unique: true
  end
end

然而,你们其余的控制器逻辑混乱并且过于复杂。我会区分updatecreate的路线:

class BookingsController < ApplicationController

  before_action :set_order, only: [:create, :index]
  before_action :set_order, only: [:create, :index]

  # POST /orders/:order_id/bookings
  def create
    @booking = @order.bookings.new(booking_params)
    if @booking.save
      redirect_to @order
    else
      render :new
    end
  end

  # PATCH /bookings/:id
  def update
    if @booking.update(:booking_params)
      redirect_to @order
    else
      render :edit
    end
  end

  private

  def set_order
    @order = Order.find(params[:id])
  end

  def set_booking
    @booking = Booking.find(params[:id])
  end

  def booking_params
    params.require(:booking)
          .permit(:product_id)
  end
end

另一种选择是使用accepts_nested_attributes - 但要尽量保持简单。