Ruby on rails ActiveRecord:如何执行';或';合并

Ruby on rails ActiveRecord:如何执行';或';合并,ruby-on-rails,ruby,activerecord,Ruby On Rails,Ruby,Activerecord,我试图在一个模型中解耦ActiveRecord查询,以便它们在不同的环境中可重用。为了简单起见,假设我有一个名为Product的模型: class Product < ActiveRecord::Base def self.over_stocked where('stock_count >= ?', 20) end def self.expensive where('price >= ?', 100.0) end end 但是,如何使用这两种

我试图在一个模型中解耦ActiveRecord查询,以便它们在不同的环境中可重用。为了简单起见,假设我有一个名为Product的模型:

class Product < ActiveRecord::Base
  def self.over_stocked
    where('stock_count >= ?', 20)
  end

  def self.expensive
    where('price >= ?', 100.0)
  end
end
但是,如何使用这两种方法为昂贵或库存过剩的产品创建新查询? 例如:


基本上,我在寻找类似于
merge
的东西,它使用OR而不是AND。理想情况下,该解决方案将返回ActiveRecord关系,而不是数组。显然,我可以用
where('stock\u count>=?或price>=?',20100.0)
重写查询,但是这不会很枯燥

我想出了以下解决方案。人们可以争论它有多干燥

class Product < ActiveRecord::Base
  scope :over_stocked, -> { where.not(stock_count: [0..19]) }
  scope :expensive, -> { where.not(price: [0..99]) }
  scope :costly_stock, -> { expensive.over_stocked }
  scope :neither_expensive_nor_over_stocked, -> { where(stock_count: [0..19]).where(price: [0..99]) }

  def self.expensive_or_over_stocked
    Product.where.not(id: Product.neither_expensive_nor_over_stocked.pluck(:id))
  end
end
类产品{where.not(库存计数:[0..19]))
范围:昂贵,->{where.not(价格:[0..99]))
经营范围:高价库存,->{priced.over\u stocked}
范围:既不贵也不库存过剩,->{其中(库存数量:[0..19])。其中(价格:[0..99])
def self.价格昂贵或库存过剩
Product.where.not(id:Product.not\u昂贵\u或\u库存过多。采摘(:id))
结束
结束

我认为这个问题没有一个简单的答案。我希望有人能证明我错了。@Pete-请看这里的问题:@Master_Yoda谢谢,我看到了这个问题,但不幸的是,它没有解决我的目标,即使用and或or合并可重用和解耦的查询。我也不认为加入Arel是一个优雅的解决方案,我同意,但请注意,在一个非常流行的问题中,社区中最受欢迎的答案是你的非干性方法。看起来AR并不真正支持你想要的。你可以试试这个。在链接答案中遇到它,未尝试过如果您使用
select
而不是
pulk
它应该通过子查询执行一个查询,而不是两个查询。
...
def expensive_or_over_stocked
  # SQL => '... WHERE stock_count >= 20 OR price >= 100.0'
  ...
end
class Product < ActiveRecord::Base
  scope :over_stocked, -> { where.not(stock_count: [0..19]) }
  scope :expensive, -> { where.not(price: [0..99]) }
  scope :costly_stock, -> { expensive.over_stocked }
  scope :neither_expensive_nor_over_stocked, -> { where(stock_count: [0..19]).where(price: [0..99]) }

  def self.expensive_or_over_stocked
    Product.where.not(id: Product.neither_expensive_nor_over_stocked.pluck(:id))
  end
end