# How to get the children of a \*collection\* of parent objects?

**URL:** <https://www.ruby-forum.com/t/how-to-get-the-children-of-a-collection-of-parent-objects/80411>\
**Category:** Rails\
**Created:** [December 26, 2006, 10:11am UTC](https://www.ruby-forum.com/t/how-to-get-the-children-of-a-collection-of-parent-objects/80411 "2006-12-26T10:11:20Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![adambeazley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/5f9b8f/32.png) [@adambeazley](https://www.ruby-forum.com/u/adambeazley)\
**Post date:** [December 26, 2006, 10:11am UTC](https://www.ruby-forum.com/t/how-to-get-the-children-of-a-collection-of-parent-objects/80411/1 "2006-12-26T10:11:20Z")

</div>

I frequently need to do something like the following (pseudo-code):

Company.find(:conditions =\> ["city == ‘Sandusky’]).employees

This of course doesn’t work because Company.find returns an array of  
companies, and ‘employees’ is not a defined method for Array.

But you know what I mean. Is there a canonical way of doing this that  
doesn’t involve lots of manual iterating? It becomes especially critical  
as the find becomes complicated.

And what about if I want distinct employees from the above example  
(assume they’re part timers who could work at many companies)?

Thanks!

/afb

---

<div class="post-metadata">

**Author:** ![adambeazley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/5f9b8f/32.png) [@adambeazley](https://www.ruby-forum.com/u/adambeazley)\
**Post date:** [December 26, 2006, 10:12am UTC](https://www.ruby-forum.com/t/how-to-get-the-children-of-a-collection-of-parent-objects/80411/2 "2006-12-26T10:12:54Z")

</div>

I should clarify that I didn’t define a relationship (has-many or HABTM)  
in the above example, since ideally there would be a solution that works  
in either case.

/afb

---

<div class="post-metadata">

**Author:** ![adambeazley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/5f9b8f/32.png) [@adambeazley](https://www.ruby-forum.com/u/adambeazley)\
**Post date:** [December 26, 2006, 10:57am UTC](https://www.ruby-forum.com/t/how-to-get-the-children-of-a-collection-of-parent-objects/80411/3 "2006-12-26T10:57:17Z")

</div>

> I frequently need to do something like the following (pseudo-code):
> 
> Company.find(:conditions =\> ["city == ‘Sandusky’]).employees

If i understood it well, you have two tables, Companies and employees,  
and you want to get all the employees from several companies given some  
conditions.

ActiveRecord makes it pretty-straight forward to get this.

Employee.find(:all, :include=\>:company,  
:conditions=\>“companies.city=‘Sandusky’”)

If you want to get unique results, you could use uniq over the resulting  
array, but since we are using include, the array you are getting is  
including the companies too; with a bit of mapping, we can just filter  
that out.

Employee.find(:all, :include=\>:company,  
:conditions=\>“companies.city=‘Sandusky’”).map{|e| e.attributes}.uniq

this way, you are converting the resulting array in an array with only  
the attributes of Employee model, and now you can just use uniq to  
remove any dupplicates.

Another approach in order to avoid the mapping would be not using  
:include, but :join and :select, with the only “problem” that you have  
to tell ActiveRecord how to join the tables and I would say is a bit  
less idiomatic because you are in some way breaking the ORM pattern.  
Also, if you are joining tables through a many to many relationship with  
another table in the middle, the join could get tricky, so I’d recommed  
to go with the :include/map solution.

regards,

javier

removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![adambeazley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/5f9b8f/32.png) [@adambeazley](https://www.ruby-forum.com/u/adambeazley)\
**Post date:** [December 26, 2006, 5:10pm UTC](https://www.ruby-forum.com/t/how-to-get-the-children-of-a-collection-of-parent-objects/80411/4 "2006-12-26T17:10:34Z")

</div>

> Employee.find(:all, :include=\>:company,  
> :conditions=\>“companies.city=‘Sandusky’”)

:include executes the default join, okay. Didn’t know that. Does that  
work if your association is many-to-many using :through?

> Employee.find(:all, :include=\>:company,  
> :conditions=\>“companies.city=‘Sandusky’”).map{|e| e.attributes}.uniq

And using map + uniq is something I have not seen before.

That’s very helpful, thanks!

/afb

---

<div class="post-metadata">

**Author:** ![adambeazley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/5f9b8f/32.png) [@adambeazley](https://www.ruby-forum.com/u/adambeazley)\
**Post date:** [December 26, 2006, 5:49pm UTC](https://www.ruby-forum.com/t/how-to-get-the-children-of-a-collection-of-parent-objects/80411/5 "2006-12-26T17:49:34Z")

</div>

> Just in case I misled you. Actually uniq has nothing to do with “map”.

Right. Your clarification is very helpful. Thanks again!

/afb

---

<div class="post-metadata">

**Author:** ![adambeazley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/5f9b8f/32.png) [@adambeazley](https://www.ruby-forum.com/u/adambeazley)\
**Post date:** [December 26, 2006, 5:35pm UTC](https://www.ruby-forum.com/t/how-to-get-the-children-of-a-collection-of-parent-objects/80411/6 "2006-12-26T17:35:48Z")

</div>

> :include executes the default join, okay. Didn’t know that. Does that  
> work if your association is many-to-many using :through?  
> include makes an outer join with the table described in the association  
> declaration (the has\_many or has\_one or whatever in the Model). All the  
> supported associations can be included, and since it’s an outer join,  
> you always get all the results for your main table and only the matching  
> rows for the included one

> > Employee.find(:all, :include=\>:company,  
> > :conditions=\>“companies.city=‘Sandusky’”).map{|e| e.attributes}.uniq
> 
> And using map + uniq is something I have not seen before.  
> Just in case I misled you. Actually uniq has nothing to do with “map”.  
> Uniq takes an array and eliminates duplicates. Map takes an array and  
> returns a different array containing whatever we return in the block.

The reason for using map here is that the array returned by find was  
including both the fields of Employee and Company, so you wouldn’t have  
any duplicates and running uniq would do nothing. What we are doing is  
using map to get a new array containing only the columns of Employee, so  
now we can let uniq do its work and clean our list.

regards,

javier ramirez
