I started a new RoR project recently, and for the first time tried using migrations. They're mildly acceptable yet I still find myself not caring much for them.
The benefits of migrations as I understand it (and why those benefits don't matter to me) are:
- You get to "version control" your database schema.
But if I want version control, I'll use a real version control system. A bunch of files in a directory sorted by a numeric prefix is rudimentary compared with Bazaar or SVN or anything else.
Migrations also require you to write all the code to "rollback" your changes yourself by hand, which is tedious. Every time I write an
add_column I have to write a corresponding
remove_column too. Many times I've gotten the add part right, and typoed the remove part, so the migration was broken, and I didn't realize until much later. Many times I wrote a remove part that I never ever had a need to use.
Because migrations are a single big long linear path, rolling way back to some point in history will obliterate a lot of changes you may want to keep that were made after that point; the older a migration is, the less likely you'll ever run it again.
Maybe I should be unit testing my migrations, you may say. I say what's the point? I'm adding a column to a DB. Do I really need to test that? Unit testing is fine, but there's a point beyond which it becomes silly. Especially for a web app, especially for something so trivial. * You can write DB stuff in Ruby rather than writing SQL manually.
This saves you a little bit of effort. But if you know SQL, it's not THAT hard to write an
ALTER TABLE query. In fact given the whole
script/generate migration SomeLongName step and then opening and editing and saving and testing and uploading and running the migration file, it's actually far faster for me to drop into a mysql prompt and do it that way.
There are also some things you can't do with Rails migration methods, and you need raw SQL. In which case you end up writing SQL anyways. Depending what you're doing, this may never happen or it may happen frequently enough to be annoying.
* You can deploy your DB changes by uploading the migrations and running
This is a good thing, but you can also save some SQL into a text file and run it by piping it into mysql from the command line, or importing it via phpmyadmin, or various other methods. * Migrations are database-agnostic, whereas SQL is usually tied to a single database.
My first reaction is, so what? What are the chances that I'm going to change my DB engine? Not very likely in the kinds of things I work on. My second reaction is that the kind of queries you write to create and edit tables are so generic that they're likely to work in most or all DB engines that Ruby supports anyways, or will work after minor edits.
- Migrations do some magic things like automatically setting up an id field for your models etc.
This is the only real benefit to migrations that I can see: a small amount of time savings and convenience and integration with the rest of the tangled mess of RoR.
What I'm trying right now is writing all my table creation code in SQL, putting it all into .sql files, and putting those files under version control in Bazaar. This is better version control than migrations offer. And my table definitions are completely intact in a single file each, which is easily browsable and editable. (I think Rails lets you export schemas too, but it's not as nice as having them in files to look at and edit directly in my opinion.) If I want to see differences in my schema over time, I can
bzr diff the files that contain them. If I want to take a single table and reproduce it in some DB somewhere, I can run that single .sql file. If I want to deploy, I rsync the files to my server and pipe them into a mysql prompt.
The good thing about RoR is that I can completely ignore migrations if I don't like them. And for my large legacy RoR app, I am ignoring them. However I plan to stick with them on this new app as far as I can; maybe more benefits will reveal themselves.