Tuesday, March 20, 2012

Rails Migrations Break Over TIme?

Here's a fun little problem.  I'm sure I'm not the only one to have run into it, but I'll document it for kicks even though I'm not quite sure yet how I'll solve it.

I just inherited a legacy codebase for a Rails 2.3.x project.  So I point to a clean database, run a rake db:create followed by a rake db:migrate, and suddenly I'm getting an error - in this case about the absence of a certain "ambassador" column in my AdminUser object.

Two things are odd.  First, there is a migration to set up that column on that object, we just haven't gotten to it yet.

Second, this migration has nothing to do with that column.

...or does it?

Here's where the time warp comes in.  The original owner of this code set up the AdminUser object, then at some point later decided he needed an ambassador column, so he wrote a migration to add it.  Fair enough.  But then after that he went in and enhanced the create method for AdminUser to say "If your ambassador flag is set, do something different."

Remember that migration that was failing?  That migration tries to insert a new AdminUser (as a mock object).  Before the column is added.

So one migration created the AdminUser object (without the ambassador column).  Next in sequence comes this innocent migration that tries to create a mock AdminUser.  However, the AdminUser can't be created without looking at the ambassador flag - which hasn't been added yet.

Not quite sure how I'm going to solve this one -- probably comment out the ambassador related code long enough to mock the object and let the migrations run.

I just found it interesting.  You inherit a Rails project, you try to run migrations, they break in the middle.  Your first thought is quite possibly, "Oh great, the last guy didn't keep his migrations up, now I have to do everything in SQL."  Maybe not the case!  This appears to be a completely innocent problem that crept in over time, and he would never have noticed it because it's not like he's constantly going back and building his database from scratch like I just did.