Q:

Rails counting through relationships

I'm having problems getting my brain around this.
I have four models: Account has many-> List has many-> ListItem <-belongs to Category
I need to get a list of the top-n Categories and the quantity count -- the ones that have the most related ListItems. To make it more complex, the Account has a "role" (say, 'team lead' and 'manager', and the count needs to be separated by that role. To summarize, I need this:
Top 5 Categories for Team Lead: Category122 (74), Category342 (67), Category22 (52), Category992 (50), Category12 (47) 
Top 5 Categories for Manager: Category1 (174), Category32 (112), Category22 (88), Category92 (73), Category5 (72) 

I keep trying to form scopes or write class methods to generate these numbers and don't get far before I get confused.
Anyone know how this type of thing can be calculated?

A:

Add this to your Account model:
has_many :list_items, :through => :lists

Then you can do this:
a = Account.first
a.list_items.joins(:category).group("categories.name").count
# => {"foo"=>1, "bar"=>2}

EDIT
@categories = Category.select("categories.name AS name, accounts.role AS role, count(list_items.id) AS count")
.joins(:list_items => {:list => :account})
.group("categories.name, accounts.role")
.order("count desc")
.limit(5)

@categories[0].role
# => Team Leader
@categories[0].count
# => 5

You'll have to add the category fields to the select, and the query looks something like:
SELECT categories.name, accounts.role, count(list_items.id) 
FROM list_items INNER JOIN lists ON lists.id = list_items.list_id 
INNER JOIN categories ON categories.id = list_items.category_id 
INNER JOIN accounts ON lists.account_id = accounts.id 
GROUP BY categories.name, accounts.role;

