RSpec and stubbing options for named scope

I am trying to write a BOM for a named scope that is date dependent.

Specification:

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 region in document model:

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

      

The spec fails with an empty array, and a query in test.log shows why:

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

      

i.e. it seems to be ignoring my Date method.

However, if I use a class method instead of a named scope, it passes:

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

      

I would prefer to use the named scope approach, but I don't understand why it doesn't work.

===

In response to @speicher:

Thanks, but Timecop doesn't seem to help here.

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

      

Still passed for class method method, but not for named scope.

I suspect named_scope is doing some kind of manipulation in the past conditions before actually evaluating them, which means Date.today is never called directly.

+2


a source to share


2 answers


I think the problem is that Date.today is not calculated at runtime, but when the model is first read by rails. Try to include it in the lambda:



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

      

+4


a source


Save yourself some headaches and use the Timecop gem to fake a date or time.



+1


a source







All Articles