我正在尝试建立一个客户可以预订小巴的预订系统。我已经能够获得所有数据,因此可以预订。
我试图避免其他用户在同一天预订小巴。我不确定如何在轨道上使用红宝石。
在我的预订中.rb我有
belongs_to :vehicle
belongs_to :user
在我的user.rb和vehicle.rb中我有
has_many :reservation
在我的预订控制器中我有
def new
@vehicle = Vehicle.find(params[:vehicle_id])
@reservation = Reservation.new(user_id: User.find(session[:user_id]).id)
@reservation.vehicle_id = @vehicle.id
end
我会使用验证来停止双重预订吗? 会不会像我的预订一样.rb
validates :vehicle_id, :startDate, :uniqueness => { :message => " minibus already reserved"}
虽然上述内容只允许预留车辆。
非常感谢任何帮助!
答案 0 :(得分:1)
您希望使用uniqueness验证器谎言,但您正在使用scope
选项。
他们在该页面上提供的示例与您的用例非常相似:
class Holiday < ApplicationRecord
validates :name, uniqueness: { scope: :year,
message: "should happen once per year" }
end
至于您应该验证哪一列,它并不重要。由于唯一性范围将是所有三列,它可以是任何一列:
validates :vehicle_id, uniqueness, { scope: [:startDate, user_id], message: "your message" }
您还应按照here所述向数据库添加索引(顺便说一下,这个问题与您的问题非常相似)。
答案 1 :(得分:1)
正如您已经发现的那样,您不能使用Rails的内置唯一性验证器来验证两个范围不重叠。
您必须构建自定义验证才能检查此问题。检查两个时间或日期范围A
和B
是否重叠的条件非常简单。看看这张图片。
A: |-----|
B1: |-----|
B2: |---------|
B3: |-----|
C1: |-|
C2: |-|
如果A
, B
和B.start < A.end && B.end > A.start
会重叠
将以下内容添加到您的模型中:
# app/models/reservation.rb
validate :reservations_must_not_overlap
private
def reservations_must_not_overlap
return if self
.class
.where.not(id: id)
.where(vehicle_id: vehicle_id)
.where('start_date < ? AND end_date > ?', end_date, start_date)
.none?
errors.add(:base, 'Overlapping reservation exists')
end
一些注意事项:
<=
和>=
(而非<
和>
),具体取决于您对开始和结束的定义。