Ruby on Rails has this wonderful feature, database migration. The idea is great and solves the common problem of how do you manage your data-models when you update an installation of a project. It works like this
You have a number of “migration” files, each continuing some ruby code to change a database (and code to change it back, but I’m not going to talk about that). The application remembers (via a special database table) which files have been processed, so if I want to change the database I just add in a new migration file with the appropriate commands. For example, in the project I’m working on at the moment (which is a forum) i do the following.
Migration 1: Create a table to hold the boards, and populate it with some test data
Migration 2: Create a table to hold the topics, and populate it with some test data
Migration 3: Create a table to hold the posts, and populate it with some test data
Migration 4: Create a table to hold users (part of the LoginEngine), and populate it with some test data
Migration 5: Alter the posts table to include a foreign key for the users table, update the rows in the posts table with sensible foreign key values.
This means i can go forward (or backwards) to any point in the development, and have a working database with a set of test data.
However I see two problems with this, which might have solutions, but if I haven’t yet found them.
First, migration 4 is actually code from an external engine project. Currently I have moved the migration file from the engine project into my migrations directory. However what happens if the engine project later extends or alters its data-model? I can freeze my code to use a specific version of the engine, but that rules me out of future enhancements or bug fixes. I would like my 4th migration to read “perform engine migrations unto version x”. That way I can modify the user tables if I need to, and if the engine later develops, I can work to make my code compatible with it, or if it diverges too much, freeze myself to an old version. I do actually want to modify the data-model they give me, because I want to store richer information about the users than they assume.
Secondly, when I create test data i use the ActiveRecord::Base.create method. This also uses the validation checks built into the rails model. I discovered this problem. At the same time as I created migration 5, I added a validation constraint to the model. Now if I make a new installation of my project, and run the migrations, it barfs at step 3, because the validation command in the model checks for a valid user. I suspect there is a way to turn of validation checks in the migration files, but that opens the door to possible errors. I think a better solution would be for each migration to have two files. One being the schema migrations, and one being the data migrations. That way i could run all the schema modifications, which would create the user_id column in my posts table, then a sensible default would pass the validation checks when I later stuff in my test data.
Technorati Tags : Rails, Migration