【问题标题】:How check time overlaps in rails检查时间如何在 Rails 中重叠
【发布时间】:2016-08-25 23:41:01
【问题描述】:

我创建了一个模型:Lecture(start_time, end_time, location)。我想编写验证函数来检查新讲座的时间是否与数据库中保存的讲座重叠。这样我就可以知道那个位置是否在那个时候被占用。我的功能是:

class Lecture < ActiveRecord::Base

validates :title, :position, presence: true

validates :start_time, :end_time, format: { with: /([01][0-9]|2[0-3]):([0-5][0-9])/,
         message: "Incorrect time format" }

validate: time_overlap

def time_overlap
    Lecture.all.each do |user| 
       if (user.start_time - end_time) * (start_time - user.end_time) >= 0                       
       errors.add(:Base, "time overlaps")
       end
     end 
end

end

错误信息:LecturesController#create 中的 NoMethodError nil:NilClass 的未定义方法“-@”。这个函数怎么写成正确的格式?

【问题讨论】:

  • 您提到您的控制器出现错误,但仍未添加控制器代码??
  • 您在lectures_controller.rbcreate 方法中有错字(顺便说一句,您忽略了发布)。撇开这一点不谈,你处理时间冲突的方法是低效的。与其从数据库中加载所有讲座并在 Ruby 中进行比较,不如构建一个查询来选择具有 start_time new_lecture.end_time 的讲座。不要在应用程序代码中做你的数据库可以为你做的事情。
  • 控制器在没有 time_overlap 函数的情况下工作正常,我只是不明白在这种情况下 ''undefined method `-@' for nil:NilClass" 是什么。我猜我在 time_overlap 中的代码有错误的 ruby​​ 样式。希望知道如何检查时间是否与正确的代码重叠。
  • -@ 是一种方法:尝试输入1.send(:-@)。它代表否定。现在尝试输入nil.send(:-@)。在某处你有一个 nil 值,可能是 start_time 或 end_time,试图被否定。也尝试输入Time.zone.now - nil。这应该会引导您朝着正确的方向前进。
  • @runchu 我会支持将过滤移动到数据库中的建议,特别是因为每次保存讲座对象都会运行。您也可以仅在创建时或开始或结束时间更改时验证这种方式。不过,无论如何,@MarsAtomic 你的效率是对的,但你的查询不包括所有可能的重叠讲座。我会使用已经编写的逻辑来输入查询:Lecture.where("(lectures.start_time - ?) * (? - lectures.end_time) &gt;= 0", self.end_time, self.start_time).present?

标签: ruby-on-rails ruby model


【解决方案1】:

看看 Ruby 2.3.0 的 Time 类:http://ruby-doc.org/core-2.3.0/Time.html

您可以使用它来检查一个 Time 实例是在另一个 Time 实例之前还是之后,例如:

t1 = Time.now
t2 = Time.now
t1 < t2
=> true
t1 > t2
=> false

因此,要检查数据库中现有讲座期间是否存在给定时间,您可以编写一些 Ruby 来检查提议的讲座的开始时间或结束时间是否位于任何现有讲座的开始时间之后和结束时间之前讲座。

【讨论】:

  • 值得一提的是,虽然&lt; 通常足够好,但您还需要在比较之前验证两个值的“存在”。
【解决方案2】:

假设您有两个时间段,例如:

start_time_a
end_time_a
start_time_b
end_time_b

两个时隙之间可能存在重叠的三种可能情况。

1) start_time_b &gt;= start_time_a &amp;&amp; start_time_b =&lt; end_time_a(即插槽 b 开始于插槽 a 中间的某个位置)
2)end_time_b &gt;= start_time_a &amp;&amp; end_time_b &lt;= end_time_a(即插槽 b 结束于插槽 a 之间)
3)start_time_b &lt;= start_time_a &amp;&amp; end_time_b &gt;= end_time_a(即槽b大于槽a,完全覆盖。

如果您检查这三个条件,您可以确定两个时隙之间是否存在重叠。

条件 1 和 2 可以使用start_time_b.between?(start_time_a, end_time_a) 进行简化。

【讨论】:

    猜你喜欢
    • 2014-08-29
    • 2017-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多