11

我有一个涉及员工缺勤记录的应用程序。

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

因此,例如,如果我输入了今天开始并明天结束的缺勤记录,则不应以任何方式输入该日期范围内的另一个缺勤记录。所以我不能制作一个从前一天开始,然后在后天结束,或者任何更晚的日期。

简单地说,我需要使日期范围独一无二。

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

模型类中涉及遍历所有记录的自定义验证器需要很长时间才能完成,而且我还没有找到任何解决这个问题的 gem。我也没有找到任何简单的方法来通过模型中的唯一性来确定范围。我很难过:/

谢谢你的时间!

编辑:

class Absence < ActiveRecord::Base
attr_accessible :date, :date_ended, :status, :reason, :form, :user_id, :tempuser, :company_id
belongs_to :user
default_scope { where(company_id: Company.current_id) }

validates :date, :date_ended, :status, :reason, :form, :user_id, presence: true 
validates_numericality_of :user_id, :only_integer => true, :message => "can only be whole number."
end
4

5 回答 5

21

我使用这些:

  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

资料来源:https ://makandracards.com/makandra/984-test-if-two-date-ranges-overlap-in-ruby-or-rails

于 2013-04-27T13:08:11.850 回答
8

使用宝石validates_overlap

gem 'validates_overlap'

例如,如果您有一个名为Meetingastart_dateend_datetype 的字段的模型date,您可以轻松验证它们不重叠。

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

另一个更现实的例子,比如说 a Meetingbelongs_to a User,您可以将其范围扩大,因此它只验证特定用户的会议。

class Meeting < ActiveRecord::Base
  belongs_to User
  validates :start_date, :end_date, overlap: { scope: 'user_id',
                                             message_content: 'overlaps with Users other meetings.' }
end
于 2014-06-04T15:34:48.057 回答
8

作为对已接受答案的修改,这里有一个重叠范围,适用于不理解 DATEDIFF 的数据库

  scope :overlaps, ->(start_date, end_date) do
    where "((start_date <= ?) and (end_date >= ?))", end_date, start_date
  end

这借鉴了确定两个日期范围是否重叠的解决方案

于 2013-08-04T23:54:11.247 回答
1

有一个名为validates_overlap的 gem ,可让您轻松验证日期范围重叠。您还可以在验证中使用范围。

于 2013-12-12T23:29:17.850 回答
1

虽然 juanpastas 解决方案是正确的,但它将对创建记录有效,但可能导致更新时出现错误的否定验证。

如果您需要编辑现有记录,假设范围是 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 无关。)

于 2014-03-13T20:29:38.000 回答