2010-05-11 4 views
2

Я пытаюсь написать спецификацию для именованной области, которая зависит от даты.Параметры RSpec и stubbing для именованной области

Спецификация:

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') 

, т. Е., Кажется, игнорирует мой метод штамповки Date.

Однако, если я использую метод класса вместо имени сферы, то она проходит:

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 никогда не вызывается напрямую.

ответ

4

Я думаю, проблема в том, что Date.today не вычисляется во время выполнения, а когда модель сначала считывается рельсами. Попробуйте вставить его в лямбда:

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

Спасибо, что работает. –

1

Сохраните некоторые головные боли и используйте жемчужину Timecop, чтобы подделать дату или время.

+0

(Я ответил как отредактировал исходное сообщение, чтобы включить код). –