Ruby on rails Rails验证日期范围的唯一性

Ruby on rails Rails验证日期范围的唯一性,ruby-on-rails,validation,Ruby On Rails,Validation,我有一份涉及员工缺勤记录的申请 我需要确保每条记录的开始日期和结束日期不重叠 class Meeting < ActiveRecord::Base validates :start_date, :end_date, overlap: true end 例如,如果我输入了一个从今天开始到明天结束的缺勤记录,那么无论如何都不可能输入该日期范围内的其他记录。所以我不能做一个从前天开始,然后在后天结束,或者任何更晚的日期 简单地说,我需要使日期范围唯一 实现这一目标的最佳方式是什么 模型类

我有一份涉及员工缺勤记录的申请

我需要确保每条记录的开始日期和结束日期不重叠

class Meeting < ActiveRecord::Base
  validates :start_date, :end_date, overlap: true 
end
例如,如果我输入了一个从今天开始到明天结束的缺勤记录,那么无论如何都不可能输入该日期范围内的其他记录。所以我不能做一个从前天开始,然后在后天结束,或者任何更晚的日期

简单地说,我需要使日期范围唯一

实现这一目标的最佳方式是什么

模型类中涉及遍历所有记录的自定义验证器花费的时间太长,我还没有找到任何解决此问题的gem。我也没有找到任何简单的方法在模型中通过唯一性来确定范围。我被难住了:/

谢谢你的时间

编辑:

class缺席true、:message=>“的\u数值性\u只能是整数。”
结束
我使用这些:

  scope :overlaps, ->(start_date, end_date) do
    where "(DATEDIFF(start_date, ?) * DATEDIFF(?, end_date)) >= 0", end_date, start_date
  end

  def overlaps?
    overlaps.exists?
  end

  # Others are models to be compared with your current model
  # you can get these with a where for example
  def overlaps
    siblings.overlaps start_date, end_date
  end

  validate :not_overlap

  def not_overlap
    errors.add(:key, 'message') if overlaps?
  end

  # -1 is when you have a nil id, so you will get all persisted user absences
  # I think -1 could be omitted, but did not work for me, as far as I remember
  def siblings
    user.absences.where('id != ?', id || -1)
  end

来源:

作为对公认答案的修改,这里有一个重叠范围,适用于不了解DATEDIFF的DBs

  scope :overlaps, ->(start_date, end_date) do
    where "((start_date <= ?) and (end_date >= ?))", end_date, start_date
  end
范围:重叠,->(开始日期,结束日期)do
其中“((开始日期=?)”,结束日期,开始日期
结束

这借鉴了

的解决方案,有一个名为gem的工具,可以方便地验证日期范围重叠。您还可以在验证中使用作用域。

虽然JuanPSTAS解决方案是正确的,但它对于创建记录是有效的,但可能会导致更新时的假阴性验证

如果需要编辑现有记录,假设范围为2014-03-13..2014-06-12,并希望将其减少到2014-03-13..2014-04-12,则会出现重叠错误,因为它正在检查自身

  def siblings
    Absence_users.where('user_id = ? AND id != ?', user_id, self)
  end
将消除这一缺点。 (也应遵循Dave T的添加,因为它与DB无关。)

使用gem

例如,如果您有一个名为
Meeting
的模型,其中包含
start\u date
end\u date
字段类型为
date
,则可以轻松验证它们是否重叠

class Meeting < ActiveRecord::Base
  validates :start_date, :end_date, overlap: true 
end

可能通过创建一个模型来记录使用的日期?比如员工的缺勤日期。这比遍历所有记录要快。你能解释一下你在前面的例子中使用了哪些同级记录吗?如何实际使用重叠范围?仅通过重叠范围验证两个日期的唯一性?是否希望给定用户在给定时间段内不出现多个缺勤?假设存在此情况,则将进行更新。是的,每个用户只允许有从2013年1月1日到(例如)2013年10月1日的缺勤记录。对于该用户,这些日期之间的所有日期都禁止任何其他缺勤记录。我收到一个“未定义的nil:NilClass方法'key'”错误和“validates:not_overlap”上的“您需要提供至少一个验证”。顺便问一下,兄弟姐妹到底是什么?如果我知道的话,我可能会贡献更多。我根本不是范围界定专家,哈!编辑:啊,我看到你在新代码中定义了它。干杯
user.absences.where.not(id:id)
将生成正确的语句,不需要-1。但是需要Rails 4。老实说,使用
=

class Meeting < ActiveRecord::Base
  validates :start_date, :end_date, overlap: true 
end
class Meeting < ActiveRecord::Base
  belongs_to User
  validates :start_date, :end_date, overlap: { scope: 'user_id',
                                             message_content: 'overlaps with Users other meetings.' }
end