# Has\_many :through

**URL:** <https://www.ruby-forum.com/t/has-many-through/128710>\
**Category:** Rails\
**Created:** [February 10, 2008, 8:34pm UTC](https://www.ruby-forum.com/t/has-many-through/128710 "2008-02-10T20:34:11Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![ipaddict](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/858c86/32.png) [@ipaddict](https://www.ruby-forum.com/u/ipaddict)\
**Post date:** [February 10, 2008, 8:34pm UTC](https://www.ruby-forum.com/t/has-many-through/128710/1 "2008-02-10T20:34:11Z")

</div>

This seems like it should have been asked numerous times already, but my  
Google-fu isn’t strong enough to find the answer. DHH advocates  
separating HABTM relationships into a join model, and I need to store  
some metadata about the join, so this makes sense. The problem is  
creation order and validations.

Say, you have three models, like so:

class Foo \< AR::Base  
has\_many :bars, :through =\> :quux  
has\_many :quuxes  
end

class Bar \< AR::Base  
has\_many :quuxes, :dependent =\> :destroy  
has\_many :foos, :through =\> :quuxes  
end

class Quux \< AR::Base  
belongs\_to :foo  
belongs\_to :bar  
end

Foo is valid without any Bars, and a Bar may belong to multiple Foos.  
However, a Bar should never exist without being associated with at least  
one Foo.

So, how would you ensure that every time a Bar is created, the proper  
Quux is also created, without ever leaving an opportunity for a Bar to  
exist without a Foo?

My initial thought is that a transaction is necessary, in this order:

1. Create Bar (rollback on fail)
2. Create Quux, referencing bar.id and foo.id (rollback on fail)

How do I enforce this order and maintain database integrity in the model  
layer?

This seems silly; if there’s an obvious answer/resource I’m missing,  
please let me know. Thanks.

---

<div class="post-metadata">

**Author:** ![ipaddict](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/858c86/32.png) [@ipaddict](https://www.ruby-forum.com/u/ipaddict)\
**Post date:** [February 10, 2008, 10:16pm UTC](https://www.ruby-forum.com/t/has-many-through/128710/2 "2008-02-10T22:16:07Z")

</div>

Brandon Mitchell wrote:

> has\_many :quuxes  
> end
> 
> 1. Create Bar (rollback on fail)
> 2. Create Quux, referencing bar.id and foo.id (rollback on fail)
> 
> How do I enforce this order and maintain database integrity in the model  
> layer?
> 
> ## This seems silly; if there’s an obvious answer/resource I’m missing, please let me know. Thanks.
> 
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

This is quite simple with validations. In your Bar model you will want  
the following:

#Validate belongs to a foo  
validates\_presence\_of :foo\_id  
#Validates foo exists - ONLY use this if the foo object is already  
saved.  
validates\_associated :foos

Rails will do all the work with Quux on your behalf.

* * *

FYI, If you do not need to directly work with the Quux model itself,  
you may find it tidier to use a has\_and\_belongs\_to\_many association  
with a join table instead of your proposed has\_many :through.

Like so:

class Foo \< AR::Base  
has\_and\_belongs\_to\_many :bars, :join\_table =\> :quuxes  
end

class Bar \< AR::Base  
has\_and\_belongs\_to\_many :foos, :join\_table =\> :quuxes  
end

and have a join table called quuxes (or maybe foo\_bar depending on how  
you like to name your join tables) with columns foo\_id and bar\_id

---

<div class="post-metadata">

**Author:** ![ipaddict](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/858c86/32.png) [@ipaddict](https://www.ruby-forum.com/u/ipaddict)\
**Post date:** [February 10, 2008, 11:27pm UTC](https://www.ruby-forum.com/t/has-many-through/128710/3 "2008-02-10T23:27:20Z")

</div>

Matt wrote:

> This is quite simple with validations. In your Bar model you will want  
> the following:
> 
> #Validate belongs to a foo  
> validates\_presence\_of :foo\_id  
> #Validates foo exists - ONLY use this if the foo object is already  
> saved.  
> validates\_associated :foos
> 
> Rails will do all the work with Quux on your behalf.

This is, perhaps, what I would _like_ to do, but Bar does not have a  
foo\_id. At least, Rails 2.0.2 doesn’t seem to be proxying #foo\_id on Bar  
to #foo\_id on Quux, by default.

This has to be one of the most used paradigms in Rails \>= 1.1, but I  
can’t seem to find the “conventional” method for assuring that a Bar  
cannot be created without an associated Foo.

> FYI, If you do not need to directly work with the Quux model itself,  
> you may find it tidier to use a has\_and\_belongs\_to\_many association  
> with a join table instead of your proposed has\_many :through.

I do need to use a join model, rather than a join table. I have other  
metadata I need to store in Quux.

---

<div class="post-metadata">

**Author:** ![ipaddict](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/858c86/32.png) [@ipaddict](https://www.ruby-forum.com/u/ipaddict)\
**Post date:** [February 11, 2008, 1:18am UTC](https://www.ruby-forum.com/t/has-many-through/128710/4 "2008-02-11T01:18:14Z")

</div>

> > #Validate belongs to a foo  
> > validates\_presence\_of :foo\_id  
> > This is, perhaps, what I would _like_ to do, but Bar does not have a  
> > foo\_id. At least, Rails 2.0.2 doesn’t seem to be proxying #foo\_id on Bar  
> > to #foo\_id on Quux, by default.  
> > Apologies, that should be :foo\_ids (plural, as it is a has\_many  
> > association) and it should be managed directly by the association. It  
> > is an array of the Foo id’s associated with Bar. Updating this should  
> > be updating the quuxes table according to the associations you have  
> > set up.
