# Noobish: create migration to add foreign keys with :through attrs?

**URL:** <https://www.ruby-forum.com/t/noobish-create-migration-to-add-foreign-keys-with-through-attrs/183593>\
**Category:** Rails\
**Created:** [February 17, 2010, 3:00am UTC](https://www.ruby-forum.com/t/noobish-create-migration-to-add-foreign-keys-with-through-attrs/183593 "2010-02-17T03:00:45Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![fearless\_fool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/5e9695/32.png) [@fearless\_fool](https://www.ruby-forum.com/u/fearless_fool)\
**Post date:** [February 17, 2010, 3:00am UTC](https://www.ruby-forum.com/t/noobish-create-migration-to-add-foreign-keys-with-through-attrs/183593/1 "2010-02-17T03:00:45Z")

</div>

## I’m dipping my toe into the world of data warehousing and dimensional databases. In: [http://rails.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html](http://rails.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html) I was excited to find the following under the “many to many” section – it’s the pattern I’m looking for:

## class Assignment \< ActiveRecord::Base belongs\_to :programmer # foreign key - programmer\_id belongs\_to :project # foreign key - project\_id end class Programmer \< ActiveRecord::Base has\_many :assignments has\_many :projects, :through =\> :assignments end class Project \< ActiveRecord::Base has\_many :assignments has\_many :programmers, :through =\> :assignments end

So far so good – I created empty models for these via  
foreach m (Assignment Programmer Project)  
script/generate model $m  
end  
and then went back and hand-annotated the model files as shown above.

My questions:

- Could ActiveRecord handle more of the model creation in this case?  
If so, how?
- How do I write the migration(s) to bring the db in sync with the  
revised models?
- Should I implement this as three separate migrations?

The guide in [Active Record Migrations — Ruby on Rails Guides](http://guides.rubyonrails.org/migrations.html) shows an  
example (grep ExampleMigration), but I’m not feeling sure footed  
enough to try it unchaperoned.

(As an aside, is there some nifty reference that shows the mapping  
between ActiveRecord descriptors and the equivalent SQL? Or should I  
dig through the sources to figure that out?)

TIA.

- ff

---

<div class="post-metadata">

**Author:** ![fearless\_fool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/5e9695/32.png) [@fearless\_fool](https://www.ruby-forum.com/u/fearless_fool)\
**Post date:** [February 17, 2010, 6:01pm UTC](https://www.ruby-forum.com/t/noobish-create-migration-to-add-foreign-keys-with-through-attrs/183593/2 "2010-02-17T18:01:14Z")

</div>

fearless\_fool wrote:

> ## I’m dipping my toe into the world of data warehousing and dimensional databases. In: [http://rails.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html](http://rails.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html) I was excited to find the following under the “many to many” section – it’s the pattern I’m looking for:
> 
> ## class Assignment \< ActiveRecord::Base belongs\_to :programmer # foreign key - programmer\_id belongs\_to :project # foreign key - project\_id end class Programmer \< ActiveRecord::Base has\_many :assignments has\_many :projects, :through =\> :assignments end class Project \< ActiveRecord::Base has\_many :assignments has\_many :programmers, :through =\> :assignments end
> 
> So far so good – I created empty models for these via  
> foreach m (Assignment Programmer Project)  
> script/generate model $m  
> end  
> and then went back and hand-annotated the model files as shown above.
> 
> My questions:
> 
> - Could ActiveRecord handle more of the model creation in this case?  
> If so, how?

ActiveRecord handles none of the model creation, as far as I can tell.  
If you’re asking about whether you could have script/generate model do  
more, the answer is no, and you probably wouldn’t want to in any case.  
Excessive generated code is generally a maintenance problem.

> - How do I write the migration(s) to bring the db in sync with the  
> revised models?

script/generate model already does that for you. Look in db/migrate.

> - Should I implement this as three separate migrations?

If it’s one atomic change, then put it in one migration. One migration  
file should contain everything that is necessary to bring the database  
from one consistent state to the next consistent state.

> The guide in [Active Record Migrations — Ruby on Rails Guides](http://guides.rubyonrails.org/migrations.html) shows an  
> example (grep ExampleMigration), but I’m not feeling sure footed  
> enough to try it unchaperoned.

Live up to the fearless part of your name and try it! If you have  
problems, please ask, but give it a try first.

> (As an aside, is there some nifty reference that shows the mapping  
> between ActiveRecord descriptors and the equivalent SQL? Or should I  
> dig through the sources to figure that out?)

There’s nothing conventionally called an “ActiveRecord descriptor”.  
What do you mean here? And have you read the rdoc and guide on  
ActiveRecord associations?

> TIA.
> 
> - ff

## Best,

Marnen Laibow-Koser  
[http://www.marnen.org](http://www.marnen.org)  
removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![fearless\_fool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/5e9695/32.png) [@fearless\_fool](https://www.ruby-forum.com/u/fearless_fool)\
**Post date:** [February 17, 2010, 6:11pm UTC](https://www.ruby-forum.com/t/noobish-create-migration-to-add-foreign-keys-with-through-attrs/183593/3 "2010-02-17T18:11:09Z")

</div>

Marnen Laibow-Koser wrote:  
[…]

> > - Could ActiveRecord handle more of the model creation in this case?  
> > If so, how?
> 
> ActiveRecord handles none of the model creation, as far as I can tell.  
> If you’re asking about whether you could have script/generate model do  
> more, the answer is no, and you probably wouldn’t want to in any case.  
> Excessive generated code is generally a maintenance problem.
> 
> > - How do I write the migration(s) to bring the db in sync with the  
> > revised models?
> 
> script/generate model already does that for you. Look in db/migrate.

A bit more about these two points. If you type “script/generate model”  
at the command line, you will see help text talking about options. You  
_can_ specify field names and types which will be written into the  
generated migration file. If you don’t do this, then the migration will  
still be generated, but it will not contain any field names.

## Best,

Marnen Laibow-Koser  
[http://www.marnen.org](http://www.marnen.org)  
removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![fearless\_fool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/5e9695/32.png) [@fearless\_fool](https://www.ruby-forum.com/u/fearless_fool)\
**Post date:** [February 17, 2010, 8:32pm UTC](https://www.ruby-forum.com/t/noobish-create-migration-to-add-foreign-keys-with-through-attrs/183593/4 "2010-02-17T20:32:13Z")

</div>

fearless\_fool wrote:

> ## I’m dipping my toe into the world of data warehousing and dimensional databases. In: [http://rails.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html](http://rails.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html) I was excited to find the following under the “many to many” section – it’s the pattern I’m looking for:
> 
> class Assignment \< ActiveRecord::Base  
> belongs\_to :programmer # foreign key - programmer\_id  
> belongs\_to :project # foreign key - project\_id  
> end  
> class Programmer \< ActiveRecord::Base  
> has\_many :assignments  
> has\_many :projects, :through =\> :assignments  
> end  
> class Project \< ActiveRecord::Base  
> has\_many :assignments  
> has\_many :programmers, :through =\> :assignments  
> end  
> […]

One more thing! It occurs to me that you should know that despite what  
the Rails Guides say, you don’t have to write raw SQL to get foreign key  
constraints in Rails. Use

> **[GitHub - matthuhiggins/foreigner: Adds foreign key helpers to migrations and...](https://github.com/matthuhiggins/foreigner)**
>
> Adds foreign key helpers to migrations and correctly dumps foreign keys to schema.rb - GitHub - matthuhiggins/foreigner: Adds foreign key helpers to migrations and correctly dumps foreign keys to s...

or one of the forks of foreign\_key\_migrations (which is perhaps better  
designed than Foreigner, but seems to be sort of abandoned).

## Best,

Marnen Laibow-Koser  
[http://www.marnen.org](http://www.marnen.org)  
removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![fearless\_fool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/5e9695/32.png) [@fearless\_fool](https://www.ruby-forum.com/u/fearless_fool)\
**Post date:** [February 19, 2010, 5:40am UTC](https://www.ruby-forum.com/t/noobish-create-migration-to-add-foreign-keys-with-through-attrs/183593/5 "2010-02-19T05:40:04Z")

</div>

fearless\_fool wrote:

> @Marmen:

(Please note the correct spelling of my name. 🙂 )

> Thanks much for the pointers and guidance.

You’re welcome!

> (In retrospect, I really  
> could have asked “when is it appropriate to hand-edit a subclass of  
> ActiveRecord?”, and the answer, I think is “almost never, for simple  
> cases”.)

Where the heck did you get that idea? A large part of Rails development  
is hand-editing your ActiveRecord model classes.

Or were you talking about using raw SQL in a migration?

In general, anything in Rails can be hand-edited (except db/schema.rb).  
Rails’ generators don’t produce generated code in the sense that Java  
frameworks tend to – they just make boilerplate skeletons to save you a  
little typing.

> With this new found understanding, Matthew Higgins’s  
> Foreigner package makes sense.
> 
> - ff

## Best,

Marnen Laibow-Koser  
[http://www.marnen.org](http://www.marnen.org)  
removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![fearless\_fool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/5e9695/32.png) [@fearless\_fool](https://www.ruby-forum.com/u/fearless_fool)\
**Post date:** [February 18, 2010, 10:18pm UTC](https://www.ruby-forum.com/t/noobish-create-migration-to-add-foreign-keys-with-through-attrs/183593/6 "2010-02-18T22:18:31Z")

</div>

@Marmen:

Thanks much for the pointers and guidance. (In retrospect, I really  
could have asked “when is it appropriate to hand-edit a subclass of  
ActiveRecord?”, and the answer, I think is “almost never, for simple  
cases”.) With this new found understanding, Matthew Higgins’s  
Foreigner package makes sense.

- ff

---

<div class="post-metadata">

**Author:** ![fearless\_fool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/5e9695/32.png) [@fearless\_fool](https://www.ruby-forum.com/u/fearless_fool)\
**Post date:** [February 20, 2010, 12:47am UTC](https://www.ruby-forum.com/t/noobish-create-migration-to-add-foreign-keys-with-through-attrs/183593/7 "2010-02-20T00:47:50Z")

</div>

@Marnen: first, apologies on the misspelling – no slight intended.

After thrashing around on this forum and working through AWDwR, I can  
pose my question more succinctly. But bear with me if I still get it  
wrong…

- You use migrations to define / extend / modify the tables in your  
db.

- ActiveRecord dynamically analyzes the tables in your db and from  
that, builds glue routines between Ruby and your db.

If that’s the case, why does one need to include belongs\_to, has\_many,  
has\_one (etc) in subclasses of ActiveRecord? Since the relationships  
between tables are described by the tables themselves, it seems  
blatantly un-DRY to specify such relationships in two places. (My  
belief that all Rails code was DRY may have been my source of  
confusion in previous posts…)

Case in point: the line\_item table in the AWDwR depot example appears  
as follows. Can’t Rails deduce the LineItem#belongs\_to, the  
Product#has\_many and the Order#has\_many relationships from this?

- ff

mysql\>describe line\_items;  
describe line\_items;  
±------------±-------------±-----±----±--------±---------------+  
| Field | Type | Null | Key | Default | Extra |  
±------------±-------------±-----±----±--------±---------------+  
| id | int(11) | NO | PRI | NULL | auto\_increment  
|  
| product\_id | int(11) | NO | MUL | NULL |  
|  
| order\_id | int(11) | NO | MUL | NULL |  
|  
| quantity | int(11) | NO | | NULL |  
|  
| total\_price | decimal(8,2) | NO | | NULL |  
|  
| created\_at | datetime | YES | | NULL |  
|  
| updated\_at | datetime | YES | | NULL |  
|  
±------------±-------------±-----±----±--------±---------------+  
7 rows in set (0.00 sec)

---

<div class="post-metadata">

**Author:** ![fearless\_fool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/f/5e9695/32.png) [@fearless\_fool](https://www.ruby-forum.com/u/fearless_fool)\
**Post date:** [February 22, 2010, 11:43pm UTC](https://www.ruby-forum.com/t/noobish-create-migration-to-add-foreign-keys-with-through-attrs/183593/8 "2010-02-22T23:43:31Z")

</div>

fearless\_fool wrote:

> @Marnen: first, apologies on the misspelling – no slight intended.

None assumed.

> After thrashing around on this forum and working through AWDwR, I can  
> pose my question more succinctly. But bear with me if I still get it  
> wrong…
> 
> - You use migrations to define / extend / modify the tables in your  
> db.

Right.

> - ActiveRecord dynamically analyzes the tables in your db and from  
> that, builds glue routines between Ruby and your db.

Not really. ActiveRecord looks at the fields in each table and uses  
that information to build SQL queries and return the results as Ruby  
objects. That’s basically it.

> If that’s the case, why does one need to include belongs\_to, has\_many,  
> has\_one (etc) in subclasses of ActiveRecord?

Because ActiveRecord doesn’t automatically detect table relationships.  
Indeed, without foreign key constraints (which not all databases  
support), there is _no way_ that it could conceivably do so reliably.

> Since the relationships  
> between tables are described by the tables themselves, it seems  
> blatantly un-DRY to specify such relationships in two places.

The relationships are actually not described by the tables in all cases,  
at least not in a way that is susceptible to deduction.

> (My  
> belief that all Rails code was DRY may have been my source of  
> confusion in previous posts…)

That belief is not 100% correct. 🙂

> Case in point: the line\_item table in the AWDwR depot example appears  
> as follows. Can’t Rails deduce the LineItem#belongs\_to, the  
> Product#has\_many and the Order#has\_many relationships from this?

No.

> - ff

## Best,

Marnen Laibow-Koser  
[http://www.marnen.org](http://www.marnen.org)  
removed\_email\_address@domain.invalid
