命名范围的RSpec和存根参数

时间:2010-05-11 20:45:51

标签: ruby-on-rails rspec

我正在尝试编写一个与日期相关的命名范围的规范。

规范:

it "should return 6 months of documents" do
    Date.stub!(:today).and_return(Date.new(2005, 03, 03))
    doc_1 = Factory.create(:document, :date => '2005-01-01')
    Document.past_six_months.should == [doc_1]
end

文档模型中的命名范围:

named_scope :past_six_months,
  :conditions => ['date > ? AND date < ?', Date.today - 6.months, Date.today]

规范以空数组失败,test.log中的查询显示原因:

SELECT * FROM "documents" WHERE (date > '2009-11-11' AND date < '2010-05-11')

即。它似乎忽略了我的存根日期方法。

但是,如果我使用类方法而不是命名范围,则传递:

def self.past_six_months
    find(:all, :conditions => ['date > ? AND date < ?', Date.today - 6.months, Date.today])
end

我宁愿使用命名范围方法,但我不明白为什么它不起作用。

===

回复@speicher:

谢谢,但Timecop似乎没有帮助。

it "should return 6 months of documents" do
    d = Date.new(2005, 03, 01)
    Timecop.travel(d)
    doc_1 = Factory.create(:document, :date => '2005-01-01')
    Document.past_six_months.should == [doc_1]
end

仍然传递类方法方法,但不适用于命名范围。

我怀疑在实际评估它们之前,named_scope正在对传递的条件进行某种操作,这意味着Date.today永远不会被直接调用。

2 个答案:

答案 0 :(得分:4)

我认为问题是Date.today不是在运行时计算的,而是在第一次由rails读取模型时。尝试将其封装在lambda:

named_scope :past_six_months, lambda { {:conditions => ['date > ? AND date < ?', Date.today - 6.months, Date.today] } }

答案 1 :(得分:1)

让自己避免一些麻烦,并使用Timecop宝石假冒日期或时间。