使用Ruby on Rails开发约会管理应用程序,并尝试实现重叠验证。约会有开始和结束时间(不是DateTime格式,只是纯整数)
试图使用Ranges,但是没有用
期望实现以下目标:
数据库现有记录:
[{id:1, start_time:0; end_time:10}, {id:2, start_time:20, end_time:40}]
应该验证一个新的约会对象,以确保它不与其他约会重叠,即
{id:15, start_time:11, end_time:19}
应该成功保存
{id:16, start_time:1, end_time:9}
不应该保存(与另一个约会(id 1)重叠)
答案 0 :(得分:0)
您可以编写自定义验证。您可以使用validates
来代替validate
。不过,您将要使用日期。使用纯整数,除非您每天要删除所有记录(您不想这样做),否则您将只能处理一天。 def中的伪代码。
validate :no_overlap, on: :save
def no_overlap
# iterate through appointments on that date
# check for the overlap
# if overlap exists
# self.errors.add("Overlaps with existing appointment!")
end
答案 1 :(得分:0)
首先将这些列更改为日期时间或时间类型,以便您可以实际使用数据库日期功能。当数据库实际上可以正确表示时间/日期时,为什么要使用整数?
SQL有一个OVERLAPS
关键字,可用于检查两个时间戳之间的重叠:
SELECT "appointments".* FROM "appointments"
WHERE ((start_time, end_time) OVERLAPS (a, b))
Postgres支持它。作为农民数据库的MySQL需要a hacky workaround。
您可以通过以下方式创建“范围”:
class Appointment < ApplicationRecord
def self.overlapping(range)
self.where('(?,?) OVERLAPS (starts_at, ends_at)', range.begin, range.end)
end
end
然后您可以在custom validation中使用范围:
class Appointment < ApplicationRecord
validates :time_available
def self.overlapping(range)
self.where('(?,?) OVERLAPS (starts_at, ends_at)', range.begin, range.end)
end
def time_available
if self.class.overlapping(start_time..end_time).exists?
errors.add(:base, "time is not available")
end
end
end