Rails中的ActiveRecord时间比较

时间:2012-07-08 20:22:14

标签: ruby-on-rails sqlite activerecord time

我正在尝试编写一些范围,用于从我的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的几种变体,它们都产生了类似的结果。

1 个答案:

答案 0 :(得分:0)

正如@jdoe在评论中所说,你必须使用lambda来避免Time.current只被提取一次。