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

时间:2018-03-10 00:50:04

标签: ruby-on-rails 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

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

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

虽然上述内容只允许预留车辆。

非常感谢任何帮助!

2 个答案:

答案 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的内置唯一性验证器来验证两个范围不重叠。

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

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

BB.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

一些注意事项:

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