This question is an offshoot from HABTM associations in Rails : collecting and counting the categories of a model's children.
class Cate
You can use chain select
and group
to aggregate the count of books for each category. Your books_per_category
method may look like this:
def books_per_category
categories.select('categories.id, categories.name, count(books.id) as count').group('categories.id, categories.name').map do |c|
{
name: c.name,
count: c.count
}
end
end
This will produce the following SQL query:
SELECT categories.id, categories.name, count(books.id) as count
FROM "categories"
INNER JOIN "books_categories" ON "categories"."id" = "books_categories"."category_id"
INNER JOIN "books" ON "books_categories"."book_id" = "books"."id"
WHERE "books"."store_id" = 1
GROUP BY categories.id, categories.name
You'll want to be creating a method (or scope) on the Categories object so something like.
Category.joins(:books).select('categories.*, COUNT(books.id) as book_count').group('categories.id')
the resulting object will now have every attribute of an instance of category and respond to a method, book_count
which returns the number of books with that instances category id.
Its noteworthy to mention this will omit any categories that do not have books associated with them. if you want to include those, the query needs to be updated to the following:
Category.joins('LEFT OUTER JOIN books_categories on books_categories.category_id = categories.id').select('categories.*, COUNT(books_categories.book_id) as book_count').group('categories.id')