Ruby on rails ActiveRecord:如何执行';或';合并
我试图在一个模型中解耦ActiveRecord查询,以便它们在不同的环境中可重用。为了简单起见,假设我有一个名为Product的模型: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 但是,如何使用这两种
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