Ruby on rails 3 轨道3-';或';范围

Ruby on rails 3 轨道3-';或';范围,ruby-on-rails-3,activerecord,scope,Ruby On Rails 3,Activerecord,Scope,我们正在更新rails 2应用程序。我们一直很高兴地使用它,它提供了一个非常好的“或”范围 现在,对于Rails3,我找不到一种方法来复制它 我们有这样的代码: scope.or(Event.horse, Event.dog, Event.trap).today class Event < ActiveRecord::Base named_scope :horse, lambda { {:conditions => ["sport_category_id in (?)", Spo

我们正在更新rails 2应用程序。我们一直很高兴地使用它,它提供了一个非常好的“或”范围

现在,对于Rails3,我找不到一种方法来复制它

我们有这样的代码:

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
模型如下所示:

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
class事件[“sport\u category\u id in(?),SportCategory.find\u horse\u id]}
命名为{scope:dog,lambda{{:conditions=>[“sport\u category\u id in(?),SportCategory.find\u dog\u id]}
命名为_scope:trap,lambda{{:conditions=>[“sport_category_id in(?),SportCategory.find_trap_id]}
结束
这些范围需要分开,并在所有地方使用。这个模型实际上有几十个作用域,它们组合使用,所以我们最不想做的就是重写它们

奇怪的是,你不能把“或”范围放在一起

有人能提出一种在Rails 3中很好地实现这一点的方法吗?即使使用arel,我也不知道如何使用。
我们在不同的项目中使用meta_,但它也不提供任何类似的功能。

好的,方法是,在您的模型中(根据您的需要调整它!):

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

scope :my_scope, where(:event => ['horse', 'dog', 'trap'])
然后您可以这样使用它:

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

我从fake_arel中删除了'or'函数,并使其与rails 3.0x一起工作(不确定它是否与3.1一起工作,因为我们这里不使用它)


如果有人感兴趣,我将它放在一个:

我无法从Phil working的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

也许我不明白该把这个放在哪里。如果我把它放在我的事件模型上(比如:scope:find_scope,where(:Event=>['horse'、'dog'、'trap']),我会得到:ActiveRecord::StatementInvalid:table
events
不存在名为
events
的属性,这就是我为什么要编写:根据您的需要调整它!如果你在这里发布你的模型,我会帮你弄清楚。我已经更新了模型。我看不出您所做的是如何调用现有的作用域,这是整个问题所在。我明白了。您想将作用域合并在一起。对不起,我不知道该怎么做。我的答案是创建一个有点“静态”的范围。该死!哦,好吧。也许有比我更聪明的人可以把代码从fake_arel移植到arel!