New plugin: multiple_migration_paths

Posted by jeff

When Rails 2 came out it made it much easier to manage the view_paths and the plugin locations. Now edge rails has timestamped migrations, which opens up a whole new possibility for multiple migration paths with the same ease as view_paths.

I’ve written a plugin that does just that, and you can get it at http://github.com/zilkey/multiple_migration_paths/tree/master

Installation

Make sure you are edge rails, then:

script/plugin install git://github.com/zilkey/multiple_migration_paths.git

Summary

This allows you to store migrations in multiple directories, and they will all be run together, as if they were in the same directory. No changes have been made to any rails rake tasks, no additional tables are needed to migrate.

Take the following directory structure:

  db
  |-- migrate
  |   |-- 20080427101407_first.rb
  |   |-- 20080427101408_second.rb
  |   `-- 20080427101409_third.rb
  |-- schema.rb
  `-- your_plugin_migrations
      |-- 20080427101308_fourth.rb
      `-- 20080427101408_third.rb

You would add your custom directory by adding the following at the bottom or environment.rb or in an initializer or plugin:

1
2

  ActiveRecord::Migration.migration_paths << File.join(RAILS_ROOT,"db","your_plugin_migrations")

In this case, migrations would be run in the following order:

  • your/plugin_migrations/20080427101308_fourth.rb (it’s the first chronologically, even though it’s named “fourth”)
  • migrate/20080427101407_first.rb
  • migrate/20080427101408_second.rb
  • migrate/20080427101409_third.rb

What happens if you add a migration that comes chronologically before the last one? Rails automatically picks it up for you – so no worries!

Notice how it takes a full path – so your migrations don’t even need to be in your app (think migrations in gems)! Also, because you get to set the paths, you can have migrations from multiple gems/plugins all at the same time, and have any kind of directory structure – like:

  db
  |-- migrate
  |   |-- some_sub_folder
  |   |   `-- 20080427101409_third.rb
  |   `-- 20080427101308_fourth.rb

Important note on ordering

Rails will treat migrations in order (I believe) of the version – not in the order that they were applied to the database.

This means that if you add migration X, then add migration Y with a prior date, then migrate down and migrate up again, it will migrate down X then Y.

Also, if you add X, then a prior Y before you migrate, Y will migrate before X.

This is all standard rails behavior and would hold true for any migrations that were checked into version control at different times. I’m just reiterating it here because there is a slightly higher risk of conflicts with this plugin. Backup your database before running them.

Rake Tasks

Since all kinds of mayhem can break loose with migrations, you may want to see what migrations are in the database. You can do so with:

  rake db:migrations:files
  rake db:migrations:paths

If I have time, I can make this a bit more human readable by presenting the dates, but that’s for later…

Behind the scenes

This change was accomplished in roughly 5 lines of code, not counting whitespace and comments, but because of the way the methods were structured, I had to copy/paste an entire method from rails. As such, it’s not very future-proof, but I’ll submit it to rails core so hopefully this will be obsolete soon!

Comments

Leave a response

Comment