# Association count sorting

**URL:** <https://www.ruby-forum.com/t/association-count-sorting/191877>\
**Category:** Rails\
**Created:** [July 20, 2010, 4:23am UTC](https://www.ruby-forum.com/t/association-count-sorting/191877 "2010-07-20T04:23:29Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![badnaam](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e36b37/32.png) [@badnaam](https://www.ruby-forum.com/u/badnaam)\
**Post date:** [July 20, 2010, 4:23am UTC](https://www.ruby-forum.com/t/association-count-sorting/191877/1 "2010-07-20T04:23:29Z")

</div>

I have 3 models GrandPa, Pa, Kid

GrandPa =\> has\_many :pas  
Pa =\> has\_many kids

When I list GrandPa I would like to present the following

* * *

1 - GrandPa\_Name

2 - List of Pas sorted by the number kids each pa has in descending  
order

* * *

How do I accomplish #2?

Thanks

---

<div class="post-metadata">

**Author:** ![badnaam](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e36b37/32.png) [@badnaam](https://www.ruby-forum.com/u/badnaam)\
**Post date:** [July 20, 2010, 4:43am UTC](https://www.ruby-forum.com/t/association-count-sorting/191877/2 "2010-07-20T04:43:58Z")

</div>

Kid has one pa and has one grandpa through pa  
Pa has one to many kids and has one grandpa  
Grandpa has one to many kids and has one pa

\<%= :name[gp]

?pa = kid if from gp?

I think you should just have one model with a foreign key to parent and  
quantity of child including nil.

---

<div class="post-metadata">

**Author:** ![badnaam](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e36b37/32.png) [@badnaam](https://www.ruby-forum.com/u/badnaam)\
**Post date:** [July 20, 2010, 4:53am UTC](https://www.ruby-forum.com/t/association-count-sorting/191877/3 "2010-07-20T04:53:21Z")

</div>

Thanks.

> Grandpa has one to many kids and has one pa  
> No, Grandpa has\_many pas

I didnt quite get how you proposed listing the pas (and kid count for  
each pa) that belong to a certain grandpa

On Jul 19, 7:42 pm, Angel Robert M. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![badnaam](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e36b37/32.png) [@badnaam](https://www.ruby-forum.com/u/badnaam)\
**Post date:** [July 20, 2010, 5:15am UTC](https://www.ruby-forum.com/t/association-count-sorting/191877/4 "2010-07-20T05:15:35Z")

</div>

Here is the answer if someone else runs into this…

GrandPa.all do |gpa|  
p gpa.name  
gpa.pas.all(:joins =\> :kids, :select =\> “pas.\*, count(pas.id) AS  
kid\_count”  
:group =\> :id, :order =\> “kid\_count DESC”).each do |pa|  
p “#{pa.name} : #{pa.kid\_count}”  
end  
end

On Jul 19, 7:58 pm, Angel Robert M. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![badnaam](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e36b37/32.png) [@badnaam](https://www.ruby-forum.com/u/badnaam)\
**Post date:** [July 20, 2010, 10:24am UTC](https://www.ruby-forum.com/t/association-count-sorting/191877/5 "2010-07-20T10:24:06Z")

</div>

On 20 July 2010 03:22, badnaam [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> 2 - List of Pas sorted by the number kids each pa has in descending  
> order
> 
> * * *
> 
> How do I accomplish #2?

A crude way (untested), I am sure there are better as I suspect this  
will call count zillions of times. It should get you going and you  
can refactor when you want to.  
grandpa.pas will give you an array of pas, then simply sort this array  
by the number of kids.  
sorted = grandpa.pas.sort\_by { |p| p.kids.count }

Colin

---

<div class="post-metadata">

**Author:** ![badnaam](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e36b37/32.png) [@badnaam](https://www.ruby-forum.com/u/badnaam)\
**Post date:** [July 20, 2010, 5:01am UTC](https://www.ruby-forum.com/t/association-count-sorting/191877/6 "2010-07-20T05:01:32Z")

</div>

> Thanks.
> 
> > Grandpa has one to many kids and has one pa  
> > No, Grandpa has\_many pas

How is this possible? That’s like saying I have two left arms.

> I didnt quite get how you proposed listing the pas (and kid count for  
> each pa) that belong to a certain grandpa

Because the sort is to easy to explain. What you’re sorting and why is  
the  
problem. So, now that I have two left arms how do I sort them by thumb  
length on my right arm. Well, I guess get a mirror.

---

<div class="post-metadata">

**Author:** ![badnaam](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/e36b37/32.png) [@badnaam](https://www.ruby-forum.com/u/badnaam)\
**Post date:** [July 20, 2010, 10:41am UTC](https://www.ruby-forum.com/t/association-count-sorting/191877/7 "2010-07-20T10:41:05Z")

</div>

On 20 July 2010 04:14, badnaam [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Here is _AN_ answer if someone else runs into this…

Your solution may certainly work… but is a bit “imperative” in  
coding terms, and does introduce an n+1 problem.

Rails offers a feature called “counter\_cache” on associations - which  
gives you a column in associate keeping track of the amount of  
“belonging” records.

Have a look for it in the manual here:  
[http://rails.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html](http://rails.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html)

If you use it, you can then just do a normal find without the block  
and order by the counter-cache column, which avoids all the extra SQL  
counts.
