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.