我们正在更新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,但它也没有提供任何这样的东西。
答案 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