想象一下,我是一个具有以下数据库结构的电子商务网站:
我想在我的订单模型中创建一个能够按总价格过滤订单的范围。这是订单的总和(order_item数量* order_item'产品价格)。
预期用途:
#Get orders that have a total cost greater than 10
Order.filter_cost('gt', 10)
这是我到目前为止所形成的,但它似乎并没有完全奏效。我认为我不应该分组,但如果我不使用分组,则会出错。使用以下范围,我得到一个响应,但返回的集合不准确。
scope :filter_cost, (lambda do |*args|
if args[0] && %w(gt lt et).include?(args[0]) && args[1]
operator_map = { 'gt' => '>', 'lt' => '<', 'et' => '=' }
joins(order_items: :product).group('orders.id').group('order_items.id').group('products.id').having("SUM(products.price * order_items.quantity) #{operator_map[args[0]]} ?", args[1].to_f)
end
end)
我可以就我的查询有什么问题获得一些指导吗?
答案 0 :(得分:0)
def self.total_cost(direction, amount)
select(orders.*, SUM(products.price * order_items.quantity) AS total_price).
joins(order_items: :product).
where(SUM(products.price * order_items.quantity) #{direction} #{amount})
end
现在您可以像Order.total_cost(:>, 10)
一样使用它
附: - 您甚至可以通过将其作为此查询返回的实例上的方法来访问total_amount
。
与Order.total_cost(:>, 10).first.total_cost
一样(返回该项目的总费用)
我认为使用符号代替gt
和lt
会更好,因为对于任何人来说这个方法更直接+你不必做不必要的映射。
可能不是最优雅的解决方案,但它确实有效。