Rails 3.1 named_scope

编写下面代码的Rails 3.1是什么:

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

写作时

 scope :min_2_items_last_90_days, where(...) 

在语法上是正确的,它可能(就像你的原始代码)没有做你想象的那样。

在这两种情况下, 90.days.ago仅在加载类时评估一次,因此90天将始终是应用程序上次重新启动之前的90天。 如果您没有重新启动应用程序10天,那么您实际上是在查看过去100天内创建的内容。 您不会在开发中注意到这一点,因为您的源代码会不断被重新加载(因此会重新评估90.days )。

相反,你应该这样做

 scope :min_2_items_last_90_days, lambda { where('orders.created_at >= ?', 90.days.ago).includes(...) ... } 

这确保了每次使用示波器时都会重新评估条件。

 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(因为它很容易忘记) :使用lambda确保每次调用范围时都重新评估条件(另请参阅范围文档 )。 由于90.days.ago表达式,此处需要重新评估 – 您最终希望每次调用范围时都要评估90.days.ago 。 如果没有lambda,则不会进行重新评估,并且仅在服务器启动时评估90.days.ago表达式。