ActiveRecord включает в себя не все родительские записи? - PullRequest
0 голосов
/ 26 мая 2018

Я бы хотел, чтобы все клиенты и их продукты находились в категории «Напитки».

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

Я пробовал это, но это не всех клиентов.Это дает только клиентам, которые заказывают напитки.

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

Примечание: я не хочу фильтровать записи клиентов.Мне нужно применить фильтр к продуктам, потому что загрузка всех записей в этом случае бесполезна.

Ответы [ 2 ]

0 голосов
/ 26 мая 2018

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
0 голосов
/ 26 мая 2018

Если вам нужно отфильтровать записи, почему вы используете левое соединение?Попробуйте

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

ОБНОВЛЕНИЕ: поскольку предложение where отфильтрует базовую запись, поэтому она должна отфильтровать вашу модель Customer, вам нужно настроить joins для выбора подходящих продуктов вместо фильтрации клиентов.

category_id = Category.find_by(name: "Beverages").id
Customer.joins(orders).joins("LEFT OUTER JOIN products ON products.id = orders.product_id AND products.category_id = #{category_id}")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...