使用Timecop gem for Scopes

时间:2012-01-13 17:56:18

标签: ruby-on-rails ruby date rspec

我在Rails 3.0应用程序中指定了一个范围如下:

class DrawingList < ActiveRecord::Base
  scope :active_drawings, where('start_date <= ? AND end_date >= ?', Date.today, Date.today)
end

在我的规范中,我想这样做:

before do
  @list = DrawingList.create #things that include begin and end dates
end

it "doesn't find an active drawing if they are out of range" do
  pending "really need to figure out how to work timecop in the presence of scopes"
  Timecop.travel(2.days)
  puts Date.today.to_s
  DrawingList.active_drawings.first.should be_nil
end

正如您可能想象的那样,看跌期权确实显示Date.today是两天。但是,范围是在不同的上下文中进行评估的,因此它使用旧的“今天”。今天如何在Timecop可以影响的环境中进行评估。

谢谢!

1 个答案:

答案 0 :(得分:18)

这是一个非常常见的错误。正如您在范围使用的日期所写的那样,是加载代码时的日期。如果你重新启动应用程序(不像每次请求重新加载的开发),你是否只在重新加载代码的生产中运行它,你会在重新启动应用程序的那天获得正确的结果,但第二天结果将在一天之内,第二天之后出现等等。

定义像这样的范围的正确方法是

scope :active_drawings, lambda { where('start_date <= ? AND end_date >= ?', Date.today, Date.today)}

lambda确保每次使用范围时都会评估这些日期。