Migrations are supposed to be both a way to make your database
definition platform (db2, oracle, mysql, etc) agnostic, and a good way
to share database changes between team members.
While it works excellently for: creating a versionable database
definition, and not tying you to one database, it has several
shortcomings in my eyes.
The idea is, when you make a change, it becomes a new migration. Other
team members just update from source control, will now have a
024_add_something.rb, run rake migrate, and presto, they’re database
looks like every other developers.
The problem is, databases may change a lot. Picture a fictional
accounting system with:
001_add_users.rb,
002_add_invoices.rb,
003_add_payments.rb, etc
Now, during the course of development, the users table for instance may
change a lot. You may need to add new fields, maybe we changed the max
length for last names, now we want to track roles/user types, someone
stored home-phone as one field, but we want it broken out into area
code, exchange, etc. This could be a lot of little changes. If you add
a new migration for each one of these, it is MUCH harder than just
looking at one create_table call in one file to see the structure.
What we end up doing is just modifying the original 001_add_users.rb. A
simple rake migrate VERSON=0, followed by rake migrate brings you up to
date EXCEPT that you lose all your data. Fine in development, but now
you cap deploy to your test box with data that matters, and this
doesn’t work.
What do people think are best practices for this?
I somewhat feel that migrations, along with code in them to transform
data when moving back/forward make a lot more sense once the code has
reached a stable point, i.e. coinciding with actual releases.
Perhaps it would be cool if running migrate generated intermediate SQL
that you could check out before creating the tables, to avoid having
one table def scattered through 8 migration files.