What is the Rails 3.1 of writing the code below:
named_scope :min_2_items_last_90_days, {
:include => { :orders => :order_items },
:conditions => ['orders.created_at >= ?', 90.days.ago],
:group => 'people.id',
:having => 'COUNT(order_items.id) >= 2'
}
While writing it as
scope :min_2_items_last_90_days, where(...)
is syntactically correct, it probably (like your original code) doesn't do quite what you think.
In both cases the 90.days.ago
is evaluated once only, when the class is loaded, so the 90 days will always be 90 days before you app was last restarted. If you haven't restart your app for 10 days you'd actually be looking at stuff created in the last 100 days. You won't notice this in development because your source code is continuously being reloaded (and thus the 90.days
is reevaluated).
Instead you should do
scope :min_2_items_last_90_days, lambda { where('orders.created_at >= ?', 90.days.ago).includes(...) ... }
which ensures that the conditions will be re-evaluated every time you use the scope.
scope :min_2_items_last_90_days, lambda { where('orders.created_at >= ?', 90.days.ago).includes(:orders => :order_items).group('people.id').having('COUNT(order_items.id) >= 2') }
NB (because it's easy to forget): Using lambda ensures that the conditions are re-evaluated each time the scope is called (see also the docs on scope). And the re-evaluation is needed here due to the 90.days.ago
expression - you definitively want 90.days.ago
to be evaluated each time the scope is called. Without the lambda, no re-evaluation would happen, and the 90.days.ago
expression would be evaluated (only) when the server starts.
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