Search code examples
ruby-on-railsrubyrake

How does rake db::migrate actually work


I've just really started with Ruby and Rails, and one of the things that I find myself really enjoying is the conventions it makes you use.

I want to mimic that behavior in my own non-Ruby projects.

My question is how does it actually work? I know I can look through the Rails code, but I'm not that far enough in my understanding to know what's going on in it.

I know that it takes a baseline script and then runs update schema changes against it. But how does it know what version it's on? How would I mimic that in another framework / database?


Solution

  • Note: This is true so far as Rails 2.x. It may not hold true for rails 3, as I haven't spent as much time with Rails 3 as I would have liked.

    Rails creates a special hidden table named schema_migrations. This table has a single column named version. And there is a row in this column for every migration you have. The value being the timestamp that matches the migrations filename timestamp.

    When you migrate, it looks through all your migrations in chronological order (also happens to be alphabetical order due to the timstamp based naming convention). For every migration it looks for a matching row in the schema_migrations table. If it fails to find one, then it runs that migration, and adds the timestamp the table. If it does find one, it assumes it already ran and simply skips it.

    The result is that 2 developers can both commit migrations in any order, and it's fine. This is because Rails knows exactly what migrations have been run and which haven't, regardless of when your database first saw them.

    So to do something yourself like this, you simply need a way to permanently store this state about which steps been taken and which have not.