# :through alternate

**URL:** <https://www.ruby-forum.com/t/through-alternate/56303>\
**Category:** Rails\
**Created:** [March 30, 2006, 1:49am UTC](https://www.ruby-forum.com/t/through-alternate/56303 "2006-03-30T01:49:05Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![tamc](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/f1d935/32.png) [@tamc](https://www.ruby-forum.com/u/tamc)\
**Post date:** [March 30, 2006, 1:49am UTC](https://www.ruby-forum.com/t/through-alternate/56303/1 "2006-03-30T01:49:05Z")

</div>

I’d like to use :through to create a web of associations like:

class Thing \< ActiveRecord::Base  
has\_many :child\_things, :through =\> :thing\_thing  
has\_many :parent\_things, :through =\> :thing\_thing, :some\_other\_option?  
end

class ThingThing \< ActiveRecord::Base  
belongs\_to :thing  
belongs\_to :child\_thing, :class\_name =\> ‘Thing’, :foreign\_key =\>  
‘child\_thing\_id’  
end

The child\_things works. The parent\_things does not, or at least, I  
cannot figure out the sytnax. I would like it to issue an sql like:

SELECT things.\* FROM things INNER JOIN thing\_things ON things.id =  
thing\_things.thing\_id WHERE (thing\_things.child\_thing\_id = 6201)

Is there a way to trigger this sql using the through options?

Many thanks

Tom

---

<div class="post-metadata">

**Author:** ![tamc](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/f1d935/32.png) [@tamc](https://www.ruby-forum.com/u/tamc)\
**Post date:** [March 30, 2006, 2:36am UTC](https://www.ruby-forum.com/t/through-alternate/56303/2 "2006-03-30T02:36:30Z")

</div>

It looks like you are trying to create a self-referential has\_many  
:through association, which should work just fine for what you want.  
However you don’t have it set up properly. The :through option on a  
has\_many association must refer to another has\_many association in the  
same model. It gets to its target through the other association, thus  
the name.

Here’s an example snipped from the Rails 1.1 test code (always a good  
place to look for example code):

class Author \< ActiveRecord::Base  
has\_many :author\_favorites  
has\_many :favorite\_authors, :through =\> :author\_favorites, :order =\>  
‘name’  
end

class AuthorFavorite \< ActiveRecord::Base  
belongs\_to :author  
belongs\_to :favorite\_author, :class\_name =\> “Author”, :foreign\_key =\>  
‘favorite\_author\_id’  
end

If you need to change the name of the association from its name in the  
join model, use the :source option to specify that name. Check the docs  
on that.

I should blog an article on this soon, as it can get a bit tricky to  
combine all the options and get them to work together correctly.

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

Thomas Counsell wrote:

> I’d like to use :through to create a web of associations like:
> 
> class Thing \< ActiveRecord::Base  
> has\_many :child\_things, :through =\> :thing\_thing  
> has\_many :parent\_things, :through =\> :thing\_thing, :some\_other\_option?  
> end
> 
> class ThingThing \< ActiveRecord::Base  
> belongs\_to :thing  
> belongs\_to :child\_thing, :class\_name =\> ‘Thing’, :foreign\_key =\>  
> ‘child\_thing\_id’  
> end
> 
> The child\_things works. The parent\_things does not, or at least, I  
> cannot figure out the sytnax. I would like it to issue an sql like:
> 
> SELECT things.\* FROM things INNER JOIN thing\_things ON things.id =  
> thing\_things.thing\_id WHERE (thing\_things.child\_thing\_id = 6201)
> 
> Is there a way to trigger this sql using the through options?
> 
> Many thanks
> 
> Tom

---

<div class="post-metadata">

**Author:** ![tamc](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/f1d935/32.png) [@tamc](https://www.ruby-forum.com/u/tamc)\
**Post date:** [March 30, 2006, 9:22am UTC](https://www.ruby-forum.com/t/through-alternate/56303/3 "2006-03-30T09:22:00Z")

</div>

Thanks Josh.

I didn’t explain myself clearly. In terms of your model, I’m really  
looking for the ability to add a reverse link:

class Author \< ActiveRecord::Base  
has\_many :author\_favorites  
has\_many :favorite\_authors, :through =\> :author\_favorites, :order =\>  
‘name’

# I’d like the reverse as well:

has\_many :other\_authors\_who\_love\_me, :through =\> :author\_favourites  
end

class AuthorFavorite \< ActiveRecord::Base  
belongs\_to :author  
belongs\_to :favorite\_author, :class\_name =\> “Author”, :foreign\_key =\>  
‘favorite\_author\_id’  
end

The :source option appears to rename the association, what I want is to  
have :other\_authors\_who\_love\_me return AuthorFavorite#author by joining  
on AuthorFavorite#favorite\_author.

Is this possible?

Thanks

Tom

Josh S. wrote:

> It looks like you are trying to create a self-referential has\_many  
> :through association, which should work just fine for what you want.  
> However you don’t have it set up properly. The :through option on a  
> has\_many association must refer to another has\_many association in the  
> same model. It gets to its target through the other association, thus  
> the name.
> 
> Here’s an example snipped from the Rails 1.1 test code (always a good  
> place to look for example code):
> 
> class Author \< ActiveRecord::Base  
> has\_many :author\_favorites  
> has\_many :favorite\_authors, :through =\> :author\_favorites, :order =\>  
> ‘name’  
> end
> 
> class AuthorFavorite \< ActiveRecord::Base  
> belongs\_to :author  
> belongs\_to :favorite\_author, :class\_name =\> “Author”, :foreign\_key =\>  
> ‘favorite\_author\_id’  
> end
> 
> If you need to change the name of the association from its name in the  
> join model, use the :source option to specify that name. Check the docs  
> on that.
> 
> I should blog an article on this soon, as it can get a bit tricky to  
> combine all the options and get them to work together correctly.
> 
> –  
> Josh S.  
> [http://blog.hasmanythrough.com](http://blog.hasmanythrough.com)
> 
> Thomas Counsell wrote:
> 
> > I’d like to use :through to create a web of associations like:
> > 
> > class Thing \< ActiveRecord::Base  
> > has\_many :child\_things, :through =\> :thing\_thing  
> > has\_many :parent\_things, :through =\> :thing\_thing, :some\_other\_option?  
> > end
> > 
> > class ThingThing \< ActiveRecord::Base  
> > belongs\_to :thing  
> > belongs\_to :child\_thing, :class\_name =\> ‘Thing’, :foreign\_key =\>  
> > ‘child\_thing\_id’  
> > end
> > 
> > The child\_things works. The parent\_things does not, or at least, I  
> > cannot figure out the sytnax. I would like it to issue an sql like:
> > 
> > SELECT things.\* FROM things INNER JOIN thing\_things ON things.id =  
> > thing\_things.thing\_id WHERE (thing\_things.child\_thing\_id = 6201)
> > 
> > Is there a way to trigger this sql using the through options?
> > 
> > Many thanks
> > 
> > Tom

---

<div class="post-metadata">

**Author:** ![tamc](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/f1d935/32.png) [@tamc](https://www.ruby-forum.com/u/tamc)\
**Post date:** [March 30, 2006, 5:45pm UTC](https://www.ruby-forum.com/t/through-alternate/56303/4 "2006-03-30T17:45:15Z")

</div>

The :source option doesn’t just rename the association, but it chooses  
which association in the join model to use to join to the target model.  
I think it will do just what you want:

has\_many :other\_authors\_who\_love\_me, :through =\> :author\_favourites,  
:source =\> :author

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

Thomas Counsell wrote:

> Thanks Josh.
> 
> I didn’t explain myself clearly. In terms of your model, I’m really  
> looking for the ability to add a reverse link:
> 
> class Author \< ActiveRecord::Base  
> has\_many :author\_favorites  
> has\_many :favorite\_authors, :through =\> :author\_favorites, :order =\>  
> ‘name’
> 
> # I’d like the reverse as well:
> 
> has\_many :other\_authors\_who\_love\_me, :through =\> :author\_favourites  
> end
> 
> class AuthorFavorite \< ActiveRecord::Base  
> belongs\_to :author  
> belongs\_to :favorite\_author, :class\_name =\> “Author”, :foreign\_key =\>  
> ‘favorite\_author\_id’  
> end
> 
> The :source option appears to rename the association, what I want is to  
> have :other\_authors\_who\_love\_me return AuthorFavorite#author by joining  
> on AuthorFavorite#favorite\_author.
> 
> Is this possible?

---

<div class="post-metadata">

**Author:** ![tamc](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/f1d935/32.png) [@tamc](https://www.ruby-forum.com/u/tamc)\
**Post date:** [March 30, 2006, 8:24pm UTC](https://www.ruby-forum.com/t/through-alternate/56303/5 "2006-03-30T20:24:42Z")

</div>

Thanks again Josh, that didn’t do what I want. After much time wasted  
the solution was obvious (although a little clunky), so it is probably  
me not explaining clearly.

class Author \< ActiveRecord::Base

# Forwards

has\_many :author\_favorites  
has\_many :favorite\_authors, :through =\> :author\_favorites, :order =\>  
‘name’

Â # Backwards  
has\_many :reverse\_author\_favourites, :class\_name =\> ‘AuthorFavorite’,  
:foreign\_key =\> :favorite\_author  
has\_many :other\_authors\_who\_love\_me, :through =\>  
:reverse\_author\_favourites, :source =\> :authors  
end

class AuthorFavorite \< ActiveRecord::Base  
belongs\_to :author  
belongs\_to :favorite\_author, :class\_name =\> “Author”, :foreign\_key =\>  
‘favorite\_author\_id’  
end

Josh S. wrote:

> The :source option doesn’t just rename the association, but it chooses  
> which association in the join model to use to join to the target model.  
> I think it will do just what you want:
> 
> has\_many :other\_authors\_who\_love\_me, :through =\> :author\_favourites,  
> :source =\> :author
