I recently tried to setup ScrumPad on my new laptop windows 7 (yes, I know not an ideal environment for Ruby on Rails. The peril of doing so is a topic for another blog) from scratch and stumbled on migration decay issue. We usually don't need to set up our projects from scratch. Every now and then we would. Whoever is doing the setup from scratch would go ahead fix any issues that might crop up in our migration scripts.
We are happily doing everything through migration just because we can- from managing incremental change in schema, to loading seed data, to migrating data due to schema changes. Over time we accumulated 498 scripts! And we have many non-backward compatible changes along the way.
This got me thinking whether we are following the best practices around migration. Here are a few things that we decided to follow going forward based on my findings:
1. Incremental changes. We will only use migration to manage incremental changes to schema. Nothing more.
2. Loading seed data. We should not be using migration script to load seed data. Instead we will use ActiveRecord to load data. If we have a lot of seed data, we would use database ETL tool instead, which would be faster.
3. Irreversible schema changes. We should through ActiveRecord::IrreversibleMigration exception from the "down" method when changes are irreversible. This is recommended by the Rails core team. We were not doing this. Even if we can revert back the schema changes, we won't be able to revert back the data changes that we do as a result of schema changes. So, why bother?
4. New database setup. We should use schema.rb to setup the database from scratch, instead of using migration scripts. We should store this in the repository and always keep it up-to-date.
5. Periodic baselining. When we reach a point of irreversible change, we should re-baseline migration script to start from that point going forward. That is we discard old migration scripts, and start with the schema.rb as the new baseline schema from that point forward.
6. Migration versioning. Although the use of sequential numbers may cause conflicting migrations (migration script with the same version), we still like this over the timestamp-based versioning introduced with Rails 2. We just synchronize among ourselves (communication!) to make sure we do not step on each other's toe. As a result, we can easily understand the logical ordering among the scripts (hence the assumed dependencies, if any).
What do you think of our approach to Rails migration? What guideline (if any) do you follow with your rails migration?