【问题标题】:ActiveRecord Time Comparisons in RailsRails 中的 ActiveRecord 时间比较
【发布时间】:2012-07-08 08:09:57
【问题描述】:

我正在尝试编写一些范围,旨在从我的 sqlite 数据库中提取未来、过去和当前事件的事件。以下是我在 Event 模型中设置的范围及其附带的谓词方法:

  scope :upcoming, where("start_at >= :time", time: Time.current ).order('start_at asc')
  scope :recent, where("end_at <= :time", time: Time.current ).order('end_at desc')
  scope :current, where("start_at <= :time AND end_at >= :time", time: Time.current ).order('start_at asc')



  def upcoming?
    start_at.future?
  end

  def recent?
    end_at.past?
  end

  def current?
    end_at.future? && start_at.past?
  end

这是我从 rspec 测试中得到的结果

  is in the future
    should be upcoming
    should not be recent
    should not be current
    should be in upcoming
    should not be in recent (FAILED - 1)
    should not be in current (FAILED - 2)
  is in the past
    should not be upcoming
    should be recent
    should not be current
    should not be in upcoming
    should be in recent (FAILED - 3)
    should not be in current
  is happening now
    should not be upcoming
    should not be recent
    should be current
    should not be in upcoming
    should not be in recent
    should be in current (FAILED - 4)

正如您所见,一旦从数据库中提取日期,谓词方法测试运行良好,但在实际查询数据库时,事情就变得混乱了。

这是我正在运行以对其进行测试的 rspec(我对它有点陌生,因此这里可能存在一些问题,但我也看到范围因手动测试而失败):

  let(:future) { Event.create(start_at: start_time, end_at: end_time ) }
  let(:past) { Event.create(start_at: start_time, end_at: end_time ) }
  let(:happening) { Event.create(start_at: start_time, end_at: end_time ) }

  context "#upcoming?" do
    it { should respond_to(:upcoming?) }
  end
  context "#recent?" do
    it { should respond_to(:recent?) }
  end
  context "#current?" do
    it { should respond_to(:current?) }
  end

  context "is in the future" do
    subject(:event) { future }
    let(:start_time) { Time.now + 1.minute }
    let(:end_time) { Time.now + 1.minute + 1.second }
    it { should be_upcoming }
    it { should_not be_recent }
    it { should_not be_current }
    it "should be in upcoming" do
      Event.upcoming.should include(event)
    end
    it "should not be in recent" do
      Event.upcoming.should_not include(event)
    end
    it "should not be in current" do
      Event.upcoming.should_not include(event)
    end
  end

  context "is in the past" do
    subject(:event) { past }
    let(:start_time) { Time.now - 1.minute }
    let(:end_time) { Time.now - 1.minute + 1.second }
    it { should_not be_upcoming }
    it { should be_recent }
    it { should_not be_current }
    it "should not be in upcoming" do
      Event.upcoming.should_not include(event)
    end
    it "should be in recent" do
      Event.upcoming.should include(event)
    end
    it "should not be in current" do
      Event.upcoming.should_not include(event)
    end
  end

  context "is happening now" do
    subject(:event) { happening }
    let(:start_time) { Time.now - 1.minute }
    let(:end_time) { Time.now + 1.minute }
    it { should_not be_upcoming }
    it { should_not be_recent }
    it { should be_current }
    it "should not be in upcoming" do
      Event.upcoming.should_not include(event)
    end
    it "should not be in recent" do
      Event.upcoming.should_not include(event)
    end
    it "should be in current" do
      Event.upcoming.should include(event)
    end
  end

知道出了什么问题吗?我尝试了Time.current 的几种变体,它们都产生了相似的结果。

【问题讨论】:

  • 首先:通过 lambdas 制作你的作用域。您的方式一些Time.current 将被获取一次,并将在程序运行的所有时间内持续存在,这显然不是您想要的。
  • jdoe 说了什么。这可能是一次获取时间的问题。
  • 我之前尝试过,但实际上出现了更多错误。但是我看到 lambda 不可能是一件坏事,所以我会更新问题中的代码和测试。
  • 你必须以这种方式使用 lambda:scope :upcoming, lambda { where... }.
  • 谢谢,我现在已经尝试过了,我又回到了最初失败的地方:(

标签: ruby-on-rails sqlite activerecord time


【解决方案1】:

正如@jdoe 在他的评论中所说,您必须使用 lambda 来避免 Time.current 仅被获取一次。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-20
    • 2016-12-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-21
    • 2019-04-07
    相关资源
    最近更新 更多