避免对小巴预订系统进行双重预订

我正在尝试建立一个客户可以预订小巴的预订系统。 我已经能够获得所有数据,因此可以预订。

我试图避免其他用户在同一天预订小巴。 我不确定如何在轨道上使用ruby。

在我的预订.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 

我会使用validation来停止双重预订吗? 会不会像我的预订一样.rb

 validates :vehicle_id, :startDate, :uniqueness => { :message => " minibus already reserved"} 

虽然以上只允许预留车辆。

任何帮助都感激不尽!

正如您已经发现的那样,您无法使用Rails的内置唯一性validation器来validation两个范围不重叠。

您必须构建自定义validation才能检查此问题。 检查两个时间或日期范围AB重叠的条件非常简单。 看看这张图片。

 A: |-----| B1: |-----| B2: |---------| B3: |-----| C1: |-| C2: |-| 

如果B.start < A.end && B.end > A.startAB重叠

将以下内容添加到您的模型中:

 # 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 

一些说明:

  • 您可能需要调整数据库列和属性名称的命名,因为我不确定它是否只是一个拼写错误,或者您是否使用不遵循Ruby约定的名称。
  • 此外,您可能需要<=>= (而不是<> ),具体取决于您对start和end的定义。
  • 将条件移动到命名范围是一个好主意,并将提高可读性

您将要使用您已经在做的唯一性validation器,但使用scope选项。

他们在该页面上给出的示例与您的用例非常相似:

 class Holiday < ApplicationRecord validates :name, uniqueness: { scope: :year, message: "should happen once per year" } end 

至于你应该validation哪一列,它并不重要。 由于唯一性范围将是所有三列,因此它可以是以下任何一列:

 validates :vehicle_id, uniqueness, { scope: [:startDate, user_id], message: "your message" } 

您还应该按照此处所述向数据库添加索引(顺便提一下,这个问题与您的问题非常相似)。