【发布时间】: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