What is has_many :through really buying you over HABTM?

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)
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), 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

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

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
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

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
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

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

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
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

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.

On 7/11/06, Wes G. [email protected] 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.

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