# How do you set HABTM values during migration?

**URL:** <https://www.ruby-forum.com/t/how-do-you-set-habtm-values-during-migration/140234>\
**Category:** Rails\
**Created:** [June 12, 2008, 5:10am UTC](https://www.ruby-forum.com/t/how-do-you-set-habtm-values-during-migration/140234 "2008-06-12T05:10:10Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![dezrtdude](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/f4b2a3/32.png) [@dezrtdude](https://www.ruby-forum.com/u/dezrtdude)\
**Post date:** [June 12, 2008, 5:10am UTC](https://www.ruby-forum.com/t/how-do-you-set-habtm-values-during-migration/140234/1 "2008-06-12T05:10:10Z")

</div>

Hi All,

I’m a bit perplexed as to how to set up certain values during  
migration. My issue is similar to the following post:

[http://groups.google.com/group/rubyonrails-talk/browse\_thread/thread/95e65b9f701a8f95/8bce8ff26f996da6?lnk=gst&q=admin+migration#8bce8ff26f996da6](http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/95e65b9f701a8f95/8bce8ff26f996da6?lnk=gst&q=admin+migration#8bce8ff26f996da6)

…however, I have a setup with Users and Roles, and I need to assign  
a role to an administrative user during migration. My setup uses  
HABTM via join tables. Any ideas?

Thanks in advance.

---

<div class="post-metadata">

**Author:** ![dezrtdude](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/f4b2a3/32.png) [@dezrtdude](https://www.ruby-forum.com/u/dezrtdude)\
**Post date:** [June 12, 2008, 2:46pm UTC](https://www.ruby-forum.com/t/how-do-you-set-habtm-values-during-migration/140234/2 "2008-06-12T14:46:19Z")

</div>

Michael Williams wrote:

> Hi All,
> 
> I’m a bit perplexed as to how to set up certain values during  
> migration. My issue is similar to the following post:
> 
> [http://groups.google.com/group/rubyonrails-talk/browse\_thread/thread/95e65b9f701a8f95/8bce8ff26f996da6?lnk=gst&q=admin+migration#8bce8ff26f996da6](http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/95e65b9f701a8f95/8bce8ff26f996da6?lnk=gst&q=admin+migration#8bce8ff26f996da6)
> 
> …however, I have a setup with Users and Roles, and I need to assign  
> a role to an administrative user during migration. My setup uses  
> HABTM via join tables. Any ideas?
> 
> Thanks in advance.

I have Users, Roles, and Permissions.

migration 001

def self.up

# create your tables

create\_table :users  
# user fields  
end  
create\_table :roles  
# role fields  
end  
create\_table :permissions  
# permission fields  
end

# then the data (I know that this is a new DB, and these are

# the first two records created, so a 1, and 1 for record IDs works.

User.create( set user fields)  
Role.create( set role fields)

# I suppose I could do a find to get the IDs for User and

# Role, but I don’t need to

Permission.create(:user\_id =\> 1, :role\_id =\> 1)  
end

---

<div class="post-metadata">

**Author:** ![dezrtdude](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/f4b2a3/32.png) [@dezrtdude](https://www.ruby-forum.com/u/dezrtdude)\
**Post date:** [June 12, 2008, 4:25pm UTC](https://www.ruby-forum.com/t/how-do-you-set-habtm-values-during-migration/140234/3 "2008-06-12T16:25:51Z")

</div>

gberz3 wrote:

> …however, I have a setup with Users and Roles, and I need to assign  
> a role to an administrative user during migration. My setup uses  
> HABTM via join tables. Any ideas?

Someone may suggest a specific technical fix.

My favorite general recommendation here is something called “deprecation  
refactor”. That means you leave an old system online while developing a  
new one.  
Some deployments go out with both systems online.

So suppose we have Foo 1\<–\>\* Bar, and we need Foo _\<–\>_ Bar.  
Temporarily leave  
the foo\_id in Bar, and add a bars\_foos table. Get your tests and code  
passing  
with both has\_many and habtm in the Foo table. (This might require some  
hacks  
that belie ActiveRecord’s usual elegance, such as a Foo#get\_bars method  
that  
conglomerates both its owned and linked Bars.) Any new records should  
start  
using the new system.

Wall-to-wall unit tests are critical here, because they allow your logic  
to  
temporarily survive a bad design.

Now deploy this intermediate design, and let it “soak” into the  
database.

After you have confidence the habtm itself works - such as after a week  
of  
working on other features within the new design - _now_ you write the  
migration  
that moves records out of the has\_many association and into the habtm.  
The  
migration takes advantage of your experience with the new habtm working  
in practice.

Write a unit test for a migration like this (and any cleaner way would  
interest  
me!):

def test\_migration\_convert\_has\_many\_to\_habtm  
# assemble the database up here  
require RailsRoot + ‘db/migrate/042\_has\_many\_to\_habtm.rb’  
ConvertHasManyToHabtm.verbose = false  
ConvertHasManyToHabtm.up # activate the migration  
# assert here that foo\_id variables are cleared, and  
# that bars\_foos is populated  
end

Now deploy the migration, run the site for a while, and observe that all  
foo\_id  
fields remain empty.

Finally, write another migration that retires the Bar.foo\_id field. At  
this  
time, disable test\_migration\_convert\_has\_many\_to\_habtm (unless you want  
to start  
it by adding that field back!).

This post describes a very large, multi-phase “deprecation refactor”.  
Only use  
this beast if your data records are very complex. (Some of ours are  
still in  
progress!😉 For the simple matter of upgrading Foo.has\_many :bars, you  
should  
still do all the steps in this order (per books like /Refactoring/), but  
you  
don’t need to deploy and wait a while between each step.

–  
Phlip
