ActiveRecord包括不包括所有父记录?

时间:2018-05-26 07:13:14

标签: ruby-on-rails ruby-on-rails-4 activerecord rails-activerecord

我希望让所有客户及其产品属于“饮料”类别。

Here are my relations:

Customer has_many orders
Order has_many products through order_details
Product has_many Orders through order_details
Product belongs to Category

我试过了,但它并没有给所有客户。它仅向订购Beverages的客户提供。

 Customer.includes(orders: {products: :category}).where(categories: { category_name: "Beverages"})

注意:我不想过滤客户记录。我需要在产品上应用过滤器,因为在这种情况下加载所有记录都是无用的。

2 个答案:

答案 0 :(得分:1)

不幸的是,

Active Record没有API来执行此操作。

如果您只需要几个已知类别,可以通过添加自定义关联来实现:

class Customer ..
  has_many :beverage_orders, -> { includes(products: :categories).where(categories: { category_name: "Beverages" }) }, class_name: "Order"

(然后Customer.includes(:beverage_orders)

如果您需要支持任意类别,您的选项会变得更糟......如果客户数量不足,我会考虑跳过包含并接受N + 1查询。

否则,我建议的下一个最不好的选择是自己进行查询:

customers = Customer.all # or whatever
beverage_orders = Order.includes(products: :categories).
                        where(categories: { category_name: "Beverages" }).
                        where(customer_id: customers).
                        group_by(&:customer_id)

customers.each do |customer|
  puts "#{customer.name} ordered #{beverage_orders[customer.id].size} beverages"
  # i.e., use `beverage_orders[customer.id]` instead of `customer.orders`
end

答案 1 :(得分:-1)

如果您需要过滤记录,为何使用左连接? 尝试

Customer.joins(:orders).where(order: { product_id: Category.find_by(name: 'Beverages').products.pluck(:id) })

更新: 由于where子句会过滤基本记录,因此它应过滤您需要自定义Customer的{​​{1}}模型,以选择合适的产品,而不是过滤客户。

joins