rails 3 - '或'范围

时间:2011-07-26 08:51:34

标签: ruby-on-rails-3 activerecord scope

我们正在更新rails 2应用。我们很高兴地使用了fake_arel,这提供了一个非常好的'或'范围。

现在,使用rails 3,我无法找到复制它的方法。

我们有这样的代码:

scope.or(Event.horse, Event.dog, Event.trap).today

该模型如下所示:

class Event < ActiveRecord::Base
 named_scope :horse, lambda { {:conditions => ["sport_category_id in (?)", SportCategory.find_horse_ids] }}
 named_scope :dog, lambda { {:conditions => ["sport_category_id in (?)", SportCategory.find_dog_ids] }}
 named_scope :trap, lambda { {:conditions => ["sport_category_id in (?)", SportCategory.find_trap_ids] }}
end

这些范围需要分开并在各处使用。这个模型实际上有几十个范围,它们组合使用,所以重写它是我们想要做的最后一件事。

你不能'或'合作范围似乎很奇怪。

有人可以提出一种在Rails 3中做到这一点的方法吗?即使使用arel我也看不到如何。 我们在一个不同的项目中使用meta_where,但它也没有提供任何这样的东西。

3 个答案:

答案 0 :(得分:1)

嗯,这样做的方法是,在你的模型中(根据你的需要调整它!):

where(:event => ['horse', 'dog', 'trap'])

数组将生成一个IN语句,这就是你想要的。此外,您可以使用rails 3 scope来实现:

scope :my_scope, where(:event => ['horse', 'dog', 'trap'])

然后你可以这样使用它:

mymodel.my_scope # and possibility to chain, like :
mymodel.my_scope.where(:public => true)

答案 1 :(得分:0)

我从fake_arel中删除'或'函数,并使用rails 3.0x(不确定它是否适用于3.1,因为我们在这里不使用它)

如果我感兴趣,我已将其放入gist

答案 2 :(得分:0)

我无法通过Phil工作获得Github-gist的代码,但它激发了我提出以下内容,我认为这是一个更简单的解决方案。它使用了一个返回ActiveRecord :: Relation类的类方法。

def self.or alt_scope
  either = scoped.where_clauses.join(' AND ') 
  alternative = alt_scope.where_clauses.join(' AND ')

  Locatie.unscoped.where("(#{either}) OR (#{alternative})").
    joins(scoped.joins_values).joins(alt_scope.joins_values).
    group(scoped.group_values).group(alt_scope.group_values).
    having(scoped.having_values).having(alt_scope.having_values).
    includes(scoped.includes_values).includes(alt_scope.includes_values).
    order(scoped.order_values).order(alt_scope.order_values).
    select(scoped.select_values).select(alt_scope.select_values)
end

只需将此添加到您的班级即可。然后,您将能够按如下方式创建多个OR查询:

Event.horse.or(Event.dog).or(Event.trap)

您可以因此“存储”在范围内:

scope :horse_dog_or_trap, horse.or(Event.dog).or(Event.trap)

并进一步扩展范围,例如:

Event.horse.or(Event.dog).or(Event.trap).today