Rails 3.1 named_scope

时间:2011-12-26 17:51:32

标签: ruby activerecord ruby-on-rails-3.1

编写下面代码的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'
  }

2 个答案:

答案 0 :(得分:7)

将其写为

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(...) ... }

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

答案 1 :(得分:2)

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