# Nested has\_many :through

**URL:** <https://www.ruby-forum.com/t/nested-has-many-through/85321>\
**Category:** Rails\
**Created:** [February 12, 2007, 5:02pm UTC](https://www.ruby-forum.com/t/nested-has-many-through/85321 "2007-02-12T17:02:25Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![sheldonh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/9fc29f/32.png) [@sheldonh](https://www.ruby-forum.com/u/sheldonh)\
**Post date:** [February 12, 2007, 5:02pm UTC](https://www.ruby-forum.com/t/nested-has-many-through/85321/1 "2007-02-12T17:02:25Z")

</div>

Hi folks,

I’m using rails-1.2.2 and have run into unexpected behavior with  
has\_many :through.

I get a SQL exception reporting the use of an unknown column when I  
use has\_many :through to navigate thusly: Project → BacklogItems →   
BacklogTask → TimeEstimates.

It looks like rails omits a required join and somehow comes to believe  
that it can navigate from a BacklogTask directly to a product.

The following code is available at [Parked at Loopia](http://pastie.caboo.se/39727) for  
those of you who prefer syntax-highlighting:

* * *

# Product.find(:first).hours() generates this error:

# 

#Exception: SQLite3::SQLException: no such column:  
backlog\_tasks.product\_id: SELECT time\_estimates.\* FROM time\_estimates  
INNER JOIN backlog\_tasks ON time\_estimates.backlog\_task\_id =  
backlog\_tasks.id WHERE ((backlog\_tasks.product\_id = 1))

class Product \< ActiveRecord::Base  
has\_many :backlog\_items, :dependent =\> :destroy,  
:order =\> :name  
has\_many :backlog\_tasks, :through =\> :backlog\_items  
has\_many :time\_estimates, :through =\> :backlog\_tasks

def hours(at = Time.now)  
time\_estimates.sum(:hours, :conditions =\>  
[“time\_estimates.created\_at \<= ?”, at])  
end  
end

class BacklogItem \< ActiveRecord::Base  
belongs\_to :product  
has\_many :backlog\_tasks, :dependent =\> :destroy,  
:order =\> :name  
has\_many :time\_estimates, :through =\> :backlog\_tasks  
end

class BacklogTask \< ActiveRecord::Base  
belongs\_to :backlog\_item  
has\_many :time\_estimates, :dependent =\> :destroy,  
:order =\> :created\_at  
end

## class TimeEstimate \< ActiveRecord::Base belongs\_to :backlog\_task end

It doesn’t seem to be adapter-specific; I tried with PostgreSQL and  
had the same problem, namely that rails appears to omit a required  
join.

My guess is that you just can’t use has\_many :through this way? I’m  
hoping I’ve just missed something that’ll be obvious to fresh eyes.

Ciao,  
Sheldon.

---

<div class="post-metadata">

**Author:** ![sheldonh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/9fc29f/32.png) [@sheldonh](https://www.ruby-forum.com/u/sheldonh)\
**Post date:** [February 13, 2007, 4:44am UTC](https://www.ruby-forum.com/t/nested-has-many-through/85321/2 "2007-02-13T04:44:58Z")

</div>

Sheldon H. wrote:

> class Product \< ActiveRecord::Base  
> has\_many :backlog\_items, :dependent =\> :destroy,  
> :order =\> :name  
> has\_many :backlog\_tasks, :through =\> :backlog\_items  
> has\_many :time\_estimates, :through =\> :backlog\_tasks
> 
> * * *
> 
> My guess is that you just can’t use has\_many :through this way? I’m  
> hoping I’ve just missed something that’ll be obvious to fresh eyes.

You guessed right. has\_many :through only goes through one level of  
join model. But you can fake it in several ways, either with custom SQL  
or by navigating the joins in ruby code.

–  
Josh S.  
[http://blog.hasmanythrough.com](http://blog.hasmanythrough.com)

---

<div class="post-metadata">

**Author:** ![sheldonh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/9fc29f/32.png) [@sheldonh](https://www.ruby-forum.com/u/sheldonh)\
**Post date:** [February 13, 2007, 8:44am UTC](https://www.ruby-forum.com/t/nested-has-many-through/85321/3 "2007-02-13T08:44:23Z")

</div>

On Feb 13, 5:44 am, Josh S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> You guessed right. has\_many :through only goes through one level of  
> join model. But you can fake it in several ways, either with custom SQL  
> or by navigating the joins in ruby code.

Interestingly, there’s been a patch for this in Trac for months, but  
it hasn’t been imported because it doesn’t come with unit tests.

Honestly, why the devs insist on tests in this particular case is  
beyond me. Smells like dogma winning out over pragmatism.

Anyway, for the benefit of others who run into this, you can grab a  
patch at:

```
http://dev.rubyonrails.org/ticket/6461

```

Thanks, Josh.

Ciao,  
Sheldon.
