Модель заказа по количеству ассоциаций - PullRequest
0 голосов
/ 14 июня 2019

Я хочу заказать некоторый Продукт в моем индексном представлении по количеству этого запаса (если есть 0, то оно идет последним, а если выше 0, то оно идет первым).

У меня есть модели: Продукт, Вариант иФондовая

Модель продукта

has_many :stocks,   through: :variants

Вариантная модель

belongs_to :product

Фондовая модель

belongs_to :variant

Вот как я могу найти весь запас одногоproduct ...

 p = Product.last
 p.stocks.map(&:quantity).sum

Теперь, как мне найти количество всех товаров, от самых больших до самых маленьких?

Ответы [ 2 ]

4 голосов
/ 14 июня 2019

Если я правильно понимаю, вы ищете все Product, которые должны быть возвращены в порядке убывания, исходя из суммы количества Stock. Если это так, это должно работать для вас.

@products = Product.left_joins(variants: :stocks) 
       .group(:id)
       .select(Product.arel_table[Arel.star],
               Stock.arel_table[:quantity].sum.as('total_quantity'))
       .order('total_quantity DESC')

Это приведет к

SELECT 
  products.*,
  SUM(stocks.quantity) AS total_quantity
FROM 
  products 
  LEFT OUTER JOIN variants ON variants.product_id = products.id
  LEFT OUTER JOIN stocks ON stocks.variant_id = variants.id
GROUP BY 
  products.id
ORDER BY 
  total_quantity DESC

Что, кажется, то, что вы хотите. Это также добавит виртуальный атрибут total_quantity ко всем загруженным Product объектам, которые можно использовать для отображения без повторного попадания в базу данных, например,

@products.each do |p|
  p.total_quantity # virtual attribute equal to SUM(stocks.quantity)
end

В качестве окончательного варианта; , если вы фактически используете p.stocks.map(&:quantity).sum в своем коде, вы можете изменить это значение на p.stocks.sum(:quantity) из соображений эффективности. Это выполнит запрос SELECT SUM(), соответствующий ActiveRecord::Relation, возвращаемому p.stocks, что в общем случае будет намного лучше, чем загрузка всех объектов Stock, затем генерация Array величин и затем итеративное накопление указанного количества в числовое значение.

0 голосов
/ 14 июня 2019

Если вы просто делаете это в представлении и вам все равно, получите ли вы ActiveRecord::Relation или Array, вы можете использовать метод Enumerable # sort_by .

Например, в хамле:

- @products.sort_by { |p| p.stocks.sum(:quantity) }.reverse.each do |product|
  Qty: #{product.stocks.sum(:quantity)}

Если бы вы определили метод на Product, который вычисляет его количество, например:

def stock_quantity
  stocks.sum(:quantity)
end

Вы можете очиститьэто немного:

- @products.sort_by(&:stock_quantity).reverse.each do |product|
  Qty: #{product.stock_quantity}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...