# What is has\_many :through really buying you over HABTM?

**URL:** <https://www.ruby-forum.com/t/what-is-has-many-through-really-buying-you-over-habtm/97835>\
**Category:** Rails\
**Created:** [July 10, 2006, 9:54pm UTC](https://www.ruby-forum.com/t/what-is-has-many-through-really-buying-you-over-habtm/97835 "2006-07-10T21:54:46Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![weyus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7ab992/32.png) [@weyus](https://www.ruby-forum.com/u/weyus)\
**Post date:** [July 10, 2006, 9:54pm UTC](https://www.ruby-forum.com/t/what-is-has-many-through-really-buying-you-over-habtm/97835/1 "2006-07-10T21:54:46Z")

</div>

So having just learned how to do has\_many :through as opposed to HABTM,  
and then, being concerned that I wouldn’t get it to work, I started  
thinking about these two approaches.

It seems to me that the _only_ problem that the HM:T (has\_many :through)  
approach solves that HABTM doesn’t is the issue of the potential  
collision of id columns between your join table and one of your joined  
tables.

[ Actually, now that I read the dance-off blog  
([http://blog.hasmanythrough.com/articles/2006/04/20/many-to-many-dance-off](http://blog.hasmanythrough.com/articles/2006/04/20/many-to-many-dance-off))  
again, perhaps the other problem is HM:T is better at handling  
polymorphic has\_many associations? ]

Still, in a simple case, it seems like you could have a HABTM  
relationship between two tables that would co-exist with a separate  
model on the join table.

So, you’d have A HABTM B and B HABTM A, both specifying a join\_table of  
C, and then you would also go ahead and create an explicit model for C  
so that you could manipulate that table separately.

And since you have to explicitly create the join object anyway in order  
to set all of the attributes on it (see:  
[http://blog.hasmanythrough.com/articles/read/150](http://blog.hasmanythrough.com/articles/read/150)), wouldn’t that  
basically be the same as having a HABTM and then overriding the  
appropriate “save” methods in either A or B (or both) to take care of  
“fixing” C to be consistent with the A (or B) objects?

Just trying to justify the effort in using this approach.

Thanks,  
Wes

---

<div class="post-metadata">

**Author:** ![weyus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7ab992/32.png) [@weyus](https://www.ruby-forum.com/u/weyus)\
**Post date:** [July 10, 2006, 10:00pm UTC](https://www.ruby-forum.com/t/what-is-has-many-through-really-buying-you-over-habtm/97835/2 "2006-07-10T22:00:21Z")

</div>

On Mon, 10 Jul 2006, Wes G. wrote:

> So having just learned how to do has\_many :through as opposed to HABTM,  
> and then, being concerned that I wouldn’t get it to work, I started  
> thinking about these two approaches.
> 
> It seems to me that the _only_ problem that the HM:T (has\_many :through)  
> approach solves that HABTM doesn’t is the issue of the potential  
> collision of id columns between your join table and one of your joined  
> tables.

There’s more than that. There’s a good comparison on:

[http://blog.hasmanythrough.com/articles/category/associations](http://blog.hasmanythrough.com/articles/category/associations)

---

<div class="post-metadata">

**Author:** ![weyus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7ab992/32.png) [@weyus](https://www.ruby-forum.com/u/weyus)\
**Post date:** [July 10, 2006, 10:06pm UTC](https://www.ruby-forum.com/t/what-is-has-many-through-really-buying-you-over-habtm/97835/3 "2006-07-10T22:06:29Z")

</div>

Deirdre Saoirse M. wrote:

> On Mon, 10 Jul 2006, Wes G. wrote:
> 
> > So having just learned how to do has\_many :through as opposed to HABTM,  
> > and then, being concerned that I wouldn’t get it to work, I started  
> > thinking about these two approaches.
> > 
> > It seems to me that the _only_ problem that the HM:T (has\_many :through)  
> > approach solves that HABTM doesn’t is the issue of the potential  
> > collision of id columns between your join table and one of your joined  
> > tables.
> 
> There’s more than that. There’s a good comparison on:
> 
> [http://blog.hasmanythrough.com/articles/category/associationst](http://blog.hasmanythrough.com/articles/category/associationst)  
> Yup. I read that before I posted.

And having read it, it still seems to me that if you go ahead and create  
a model object for your join table, then you get your “primary key” and  
your “rich association” features still (as shown in the dance-off  
table), so why bother to specify the association differently - just add  
the join table model because you need it and deal with the extra  
attributes.

With HM:T, you still have to manage the join model anyway.

Wes

---

<div class="post-metadata">

**Author:** ![weyus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7ab992/32.png) [@weyus](https://www.ruby-forum.com/u/weyus)\
**Post date:** [July 11, 2006, 7:58am UTC](https://www.ruby-forum.com/t/what-is-has-many-through-really-buying-you-over-habtm/97835/4 "2006-07-11T07:58:46Z")

</div>

Josh S. wrote:

> Wes G. wrote:
> 
> > Deirdre Saoirse M. wrote:
> > 
> > > On Mon, 10 Jul 2006, Wes G. wrote:
> > > 
> > > > So having just learned how to do has\_many :through as opposed to HABTM,  
> > > > and then, being concerned that I wouldn’t get it to work, I started  
> > > > thinking about these two approaches.
> > > > 
> > > > It seems to me that the _only_ problem that the HM:T (has\_many :through)  
> > > > approach solves that HABTM doesn’t is the issue of the potential  
> > > > collision of id columns between your join table and one of your joined  
> > > > tables.
> > > 
> > > There’s more than that. There’s a good comparison on:
> > > 
> > > [http://blog.hasmanythrough.com/articles/category/associationst](http://blog.hasmanythrough.com/articles/category/associationst)  
> > > Yup. I read that before I posted.
> > 
> > And having read it, it still seems to me that if you go ahead and create  
> > a model object for your join table, then you get your “primary key” and  
> > your “rich association” features still (as shown in the dance-off  
> > table), so why bother to specify the association differently - just add  
> > the join table model because you need it and deal with the extra  
> > attributes.
> > 
> > With HM:T, you still have to manage the join model anyway.
> 
> There’s a whole other level to think about things above that of the  
> dance-off. Beyond the particular feature advantages that hmt has over  
> habtm is that it gives you a real objec to work with. The habtm  
> relationship is hidden from the world of objects - that’s a lousy fit  
> for an ORM approach. With hmt, you have a first-class object that  
> represents the relationship, which gives you all sorts of leverage, not  
> to mention a handly place to put code for managing the relationship.
> 
> Half the battle in software design is finding the right level of  
> abstraction. Since Rails is object-oriented technology, using objects is  
> generally going to be a big win for your software.
> 
> –  
> Josh S.  
> [http://blog.hasmanythrough.com](http://blog.hasmanythrough.com)

Josh,

I agree with all of that. But would things be workable if you just  
created the model object that you need for the join table and still work  
with a HABTM? You get your object, but you also get your proxy  
collections from HABTM.

Obviously, you have to enhance code somewhere to manage the join model  
object’s extra attributes.

Wes

---

<div class="post-metadata">

**Author:** ![weyus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7ab992/32.png) [@weyus](https://www.ruby-forum.com/u/weyus)\
**Post date:** [July 11, 2006, 7:51am UTC](https://www.ruby-forum.com/t/what-is-has-many-through-really-buying-you-over-habtm/97835/5 "2006-07-11T07:51:37Z")

</div>

Wes G. wrote:

> Deirdre Saoirse M. wrote:
> 
> > On Mon, 10 Jul 2006, Wes G. wrote:
> > 
> > > So having just learned how to do has\_many :through as opposed to HABTM,  
> > > and then, being concerned that I wouldn’t get it to work, I started  
> > > thinking about these two approaches.
> > > 
> > > It seems to me that the _only_ problem that the HM:T (has\_many :through)  
> > > approach solves that HABTM doesn’t is the issue of the potential  
> > > collision of id columns between your join table and one of your joined  
> > > tables.
> > 
> > There’s more than that. There’s a good comparison on:
> > 
> > [http://blog.hasmanythrough.com/articles/category/associationst](http://blog.hasmanythrough.com/articles/category/associationst)  
> > Yup. I read that before I posted.
> 
> And having read it, it still seems to me that if you go ahead and create  
> a model object for your join table, then you get your “primary key” and  
> your “rich association” features still (as shown in the dance-off  
> table), so why bother to specify the association differently - just add  
> the join table model because you need it and deal with the extra  
> attributes.
> 
> With HM:T, you still have to manage the join model anyway.

There’s a whole other level to think about things above that of the  
dance-off. Beyond the particular feature advantages that hmt has over  
habtm is that it gives you a real objec to work with. The habtm  
relationship is hidden from the world of objects - that’s a lousy fit  
for an ORM approach. With hmt, you have a first-class object that  
represents the relationship, which gives you all sorts of leverage, not  
to mention a handly place to put code for managing the relationship.

Half the battle in software design is finding the right level of  
abstraction. Since Rails is object-oriented technology, using objects is  
generally going to be a big win for your software.

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

---

<div class="post-metadata">

**Author:** ![weyus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7ab992/32.png) [@weyus](https://www.ruby-forum.com/u/weyus)\
**Post date:** [July 11, 2006, 9:35am UTC](https://www.ruby-forum.com/t/what-is-has-many-through-really-buying-you-over-habtm/97835/6 "2006-07-11T09:35:23Z")

</div>

Yep, I used push\_with\_attributes extensively on a project in the  
pre-1.0 days, and it was a real struggle to both get it working  
initially, and to try to diagnose issues when things went wrong with  
my test cases.

I can distinctly remember tearing my hair out trying to diagnose a  
problem that occurred regularly in my app, but which refused to break  
when I ran exactly the same code under the console or with  
breakpointer. I eventually had to resort to dumping multiple objects  
to the screen at the point where things went wrong, and keep refining  
what I was dumping over many instances of reproducing the problem. A  
simple task that I thought would take an hour or so eventually chewed  
up several days.

On that basis alone, I’d personally recommend staying completely away  
from HABTM except for the simplest possible cases, and even then I’d  
have to ask what quantifiable benefit you’d get from using HABTM over  
HMT that would make it worthwhile. To be fair, HABTM seems to work  
very well for simple cases, but given that HMT appears to be favoured  
over it and the problems I found with HABTM in non-simple cases, why  
would you use HABTM these days?

As both HABTM and HTM are defined in one place only (a pair of model  
files), and HABTM is only marginally simpler syntactically, I can’t  
see that a benefit of using it over HMT exists.

Regards

Dave M.

Regards

Dave M.

---

<div class="post-metadata">

**Author:** ![weyus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7ab992/32.png) [@weyus](https://www.ruby-forum.com/u/weyus)\
**Post date:** [July 11, 2006, 8:11am UTC](https://www.ruby-forum.com/t/what-is-has-many-through-really-buying-you-over-habtm/97835/7 "2006-07-11T08:11:08Z")

</div>

On 7/11/06, Wes G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > > > >
> > > 
> > > Yup. I read that before I posted.
> > 
> > generally going to be a big win for your software.  
> > with a HABTM? You get your object, but you also get your proxy  
> > collections from HABTM.
> 
> Obviously, you have to enhance code somewhere to manage the join model  
> object’s extra attributes.
> 
> Wes

The old push\_with\_attributes method used to try to get the HABTM  
relationships to contain data. From the posts back in the olden days,  
this  
looks fraught with danger. I believe it was problematic at best, and  
the  
push\_with\_attributes method is now depricated in any case.

–

---

<div class="post-metadata">

**Author:** ![weyus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7ab992/32.png) [@weyus](https://www.ruby-forum.com/u/weyus)\
**Post date:** [July 11, 2006, 1:39am UTC](https://www.ruby-forum.com/t/what-is-has-many-through-really-buying-you-over-habtm/97835/8 "2006-07-11T01:39:12Z")

</div>

Try doing them both for similar models. Make sure there is a primary  
key, a couple of extra fields, and some simple validation in both the  
join models. I think you’ll find yourself running into more problems  
with habtm than has\_many :through. Plus, has\_many :through just feels  
more natural for a slightly complex join model than habtm. You’ll  
understand when you try them both and get them both working.  
-Nathan
