This morning I wanted to drop my development database and rebuild it from the first migration on. When I ran rake db:migrate, it threw a bunch of errors. I discovered a crazy migration issue and found a fix. Here's the problem:
You have a series of migrations 0...X...Y. At migration Y, you also change a model's definition (ie: you add a "phone1" field and you add some validations to ensure that it is correct format or present or something.)
Now, you go to a new computer and check out your CVS repository (or your just drop your database and rebuild from scratch like I did.) Now you need to run migrations 0...Y, which may refer to your model. Unfortunately, they can only refer to the most current version of the model (the one which is in CVS at the time of migration Y.) As you run the migrations, you get to migration X, which involves using the model. Unfortunately, the model on disk (in app/models) from CVS is the version which corresponds to Y, not X (ie it wants to check the format of "phone1", which doesn't exist yet.)
What it should be doing is using the model that was CVS at the time of migration X, not the one that was in CVS at the time of checkout.
The solution I found was that you can redefine the models that you work with inside the migration itself. ie:
class Corrections1 < ActiveRecord::Migration
class Target < ActiveRecord::Base; end
def self.up
t = Target.find_by_id 112703
...
This means that Target.find_by_id is instantiating a dynamically created Corrections1::Target, not the Target in app/models. Unfortunately, this sometimes cascades to dependent models and you need to redefined a bunch of them. Also, it means that this is an extremely basic model which only knows about the database columns and doesn't run any of your validations. The best solution I can think of is copying the bodies of all the models you use in the migration into the migration file as you create it, so that it sticks with the migration file.
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment