我有一个产品 我有一个订单 我在两者之间预订。
每当我从产品到订单进行预订时,它都会保存一个新的唯一预订。
它应该:
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]
来获取参数。谁知道为什么?
答案 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
然而,你们其余的控制器逻辑混乱并且过于复杂。我会区分update
和create
的路线:
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
- 但要尽量保持简单。