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