Dec 09 2005
Rails Migration Issues
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.





