I'm spec'ing a scope in a Rails 3.0 app as follows:
class DrawingList < ActiveRecord::Base
scope :active_drawings, where('start_date <= ? AND end_date >= ?', Date.today, Date.today)
end
In my spec, I want to do:
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
As you might imagine, the puts really shows that Date.today is two days hence. However, the scope is evaluated in a different context, so it uses the old "today". How does one get today evaluated in a context that Timecop can affect.
Thanks!
This is a really common mistake. As you've written in the date used by the scope is the date as it was when the code was loaded. Were you to run this in production where code is only reloaded if you restart the app (unlike development where it is reloaded on each request), you'd get the right results on the day you restarted the app, but the next day the results would be out by one day, the day after by 2 days etc.
The correct way of defining a scope like that is
scope :active_drawings, lambda { where('start_date <= ? AND end_date >= ?', Date.today, Date.today)}
The lambda ensures that those dates are evaluated each time the scope is used.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With