自定义验证器以防止 Rails 4 应用程序中的重叠约会?

Custom validator to prevent overlapping appointments in Rails 4 app?

我需要帮助编写自定义验证以防止 Rails 4 应用程序中的约会重叠。我编写此应用程序是为了自学 Ruby & Rails。在研究这个问题时,我发现了一个名为 ValidatesOverlap 的 gem,但我想编写自己的验证器以供学习之用。

我的约会模型有一个 "appointment_at" 日期时间数据类型的列和一个 "duration" 时间数据类型的列。 Appointment 模型与 Member 和 Trainer 模型有 "has_many :through" 关联。约会:

belongs_to :member
belongs_to :trainer

约会模型中的现有验证包括:

validates :member, uniqueness: {scope: :appointment_at, message: "is booked already"}
validates :trainer, uniqueness: {scope: :appointment_at, message: "is booked already"}

自定义验证器需要防止成员或培训师安排重叠的约会。现在,我可以阻止 "duplicate appointments" 被保存到数据库,但不能阻止 "overlapping" 的。例如,如果 trainer_1 与 member_1 预约了 1 小时的约会,开始于 7:00 上午,我的模型验证阻止 member_2 与 [=27= 预约] 7:00 上午。但是,我目前没有办法阻止 member_2 为 7:01 安排与 trainer_1 的会话!我正在处理两个属性:"appointment_at," 是开始时间,"duration" 是约会的总时间。如果我可以轻松地从 "appointment_at" 和 "duration" 值计算出 "end time",我宁愿保留那些 attributes/columns。我还不知道该怎么做:)

对于如何解决约会重叠问题(不使用 gem)的任何想法或建议,我将不胜感激。非常感谢!

我刚才遇到了同样的问题。您需要一个作用域 :overlapping,它读取约会的重叠约会和要检查的验证器。此示例适用于 PostgreSQL 数据库。如果您使用的是其他数据库,则必须针对您的数据库进行调整。

class Appointment < ActiveRecord::Base

  belongs_to :member
  belongs_to :trainer

  validate :overlapping_appointments

  scope :overlapping, ->(a) {
     where(%q{ (appointment_at, (appointment_at + duration)) OVERLAPS (?, ?) }, a.appointment_at, a.appointment_to)
    .where(%q{ id != ? }, a.id)
    .where(trainer_id: a.trainer.id)
  }

  def find_overlapping
    self.class.overlapping(self)
  end

  def overlapping?
    self.class.overlapping(self).count > 0
  end

  def appointment_to
    (appointment_at + duration.hour.hours + duration.min.minutes + duration.sec.seconds).to_datetime
  end

  protected

  def overlapping_appointments
    if overlapping?
      errors[:base] << "This appointment overlaps with another one."  
    end
  end

end

试一试,如果对您有帮助,请告诉我。