如何在Rails 3中组合不同的范围?

时间:2012-03-14 19:23:26

标签: ruby-on-rails ruby-on-rails-3 scope conditional-statements named-scope

我的rails app中有以下命名范围:

  scope :published, :conditions => {:status => 'published'}
  scope :coming_soon, :conditions => {:status => 'coming_soon'}
  scope :in_development, :conditions => {:status => 'in_development'}
  scope :cancelled, :conditions => {:status => 'cancelld'}

我在编写一个结合了“已发布”和“很快梳理”的内容时遇到了麻烦。这是我尝试过的。

  scope :public, :conditions => {"status == published || status == coming_soon"}

有什么想法吗?

1 个答案:

答案 0 :(得分:3)

Rails 2:named_scope :public, :status => ['published', 'coming_soon']
Rails 3:scope :public, where(:status => ['published', 'coming_soon'])

Rails将看到数组并在sql中使用IN运算符。

注意:Article.published.coming_soon的另一种方法(链现有范围)不起作用,因为文章不能同时是那些东西或彼此的子集。

另一个注意事项:当你想要一些依赖于变量参数的东西时要小心。例如,你想要一个调度系统的“未来约会”,你可以写一下 [这是无效]

Rails 2:named_scope :upcoming_appts, :conditions => (['appt_dt > ?', Time.now])
Rails 3:scope :upcoming_appts, where(['appt_dt > ?', Time.now])

但是有一个问题:当范围本身时,Time.now将在第一次评估课时 进行评估评估。
为了克服这个问题,你使用lambda(愚蠢的名字,但基本上是指匿名函数 - 或者更简单地说'一个实际上没有名字的函数'),如下所示:

[这是有效]

Rails 2:named_scope :upcoming_appts, lambda {:conditions => (['appt_dt > ?', Time.now])}
Rails 3:scope :upcoming_appts, lambda {where(['appt_dt >= ?', Time.now])}

此范围现在将在每次执行时进行评估 - 使用它 - 因此Time.now将是实际的当前日期时间。