Ruby on rails Rails中的ActiveRecord时间比较

Ruby on rails Rails中的ActiveRecord时间比较,ruby-on-rails,sqlite,activerecord,time,Ruby On Rails,Sqlite,Activerecord,Time,我试图编写一些作用域,用于从我的sqlite数据库中提取未来、过去和当前事件的事件。以下是我在事件模型中设置的范围及其附带的谓词方法: 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') s

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

  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来测试itI,我对它有点陌生,所以这里可能有一些问题,但我也看到了手动测试失败的范围:

  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,它们都产生了类似的结果。

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

首先:通过lambda创建你的作用域。您的方式Time.current将被获取一次,并将一直保持程序运行,这显然不是您想要的。这可能是一次抓取时间的问题。我以前也试过,但结果却出现了更多的错误。但是我知道lambda不可能是一件坏事,所以我将更新问题中的代码和测试。您必须以这种方式使用lambda:scope:uncoming,lambda{where…}。谢谢,我已经尝试过了,现在回到了最初失败的地方:
  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