# retrieving "grandchild" data

**URL:** <https://discuss.rubyonrails.org/t/retrieving-grandchild-data/2812>\
**Category:** rubyonrails-talk\
**Created:** [October 9, 2006, 5:17am UTC](https://discuss.rubyonrails.org/t/retrieving-grandchild-data/2812 "2006-10-09T05:17:06Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Matt\_Jones1](https://avatars.discourse-cdn.com/v4/letter/m/bbce88/32.png) [@Matt\_Jones1](https://discuss.rubyonrails.org/u/Matt_Jones1)\
**Post date:** [October 9, 2006, 5:17am UTC](https://discuss.rubyonrails.org/t/retrieving-grandchild-data/2812/1 "2006-10-09T05:17:06Z")

</div>

This is a classic example of why :through was added to has\_many in 1.1 - see the excellent tutorials at:

[http://blog.hasmanythrough.com/articles/2006/02/28/association-goodness](http://blog.hasmanythrough.com/articles/2006/02/28/association-goodness)[http://blog.hasmanythrough.com/articles/2006/03/01/association-goodness-2](http://blog.hasmanythrough.com/articles/2006/03/01/association-goodness-2)

Essentially, you add an additional declaration to Library: has\_many :books, :through =\> :shelves

And then you can say

@books = @library.books

and everything should work normally.

Not sure about the next level (library-\>shelf-\>book-\>page) - any hm:t experts want to offer some advice?

---

<div class="post-metadata">

**Author:** ![eden\_li](https://avatars.discourse-cdn.com/v4/letter/e/b19c9b/32.png) [@eden\_li](https://discuss.rubyonrails.org/u/eden_li)\
**Post date:** [October 9, 2006, 6:01am UTC](https://discuss.rubyonrails.org/t/retrieving-grandchild-data/2812/2 "2006-10-09T06:01:09Z")

</div>

Max hit the fastest solution on it with find() and :include, but at the end of the day, these are all Ruby enumerables, so you can fall back onto Ruby operators (albeit at the cost of more SQL queries):

@pages = library.shelves.map { |s| s.books.map { |b| b.pages } } }.flatten

Matt Jones wrote:
