Rake tasks for run Rails engines migrations
I created a patch for run engine’s migrations
~I created a patch for run engine’s migrations, it adds two Rake tasks:
db:migrate:enginesdb:migrate:engines:down
The first one allows to run all the migrations stored in the db/migrate directory of each plugin.
It runs migrations in the same order Rails::Initializer register the plugins, this means if you force an order by environment.rb, it will be reflected on migrations order.
Example:
You have four plugins in your app: apple, bar, foo, pear.
environment.rb#
Rails::Initializer.run do |config| config.plugins = [ :foo, :bar, :all ] end
The task will run migrations in the following order: foo, bar, apple, pear.
It also add table structure declaration to your db/schema.rb (only if ActiveRecord::Base.schema_format == :ruby) and leave untouched your original version value.
This make totally independent app migrations from engine migrations.
Example:
db/migrate/20090224121645_create_birds.rb
vendor/plugins/foo/db/migrate/20080224121645_create_foos.rb vendor/plugins/foo/db/migrate/20080224121646_create_bars.rb
$ rake db:migrate # => create birds (current tables: birds) $ rake db:migrate:engines # => create foos and bars (current tables: birds, foos and bars) $ rake db:migrate VERSION=0 # => delete birds (current tables: foos and bars) $ rake db:migrate # => create birds, again (current tables: birds, foos and bars) $ rake db:migrate:engines:down # => delete foos and bars (current tables: birds)
You can also specify if run migrations only from a specific engine:
$ rake db:migrate:engines ENGINE=foo # => run migrations from 'foo' engine only
$ rake db:migrate:engines:down ENGINE=foo # => run down migrations from 'foo' engine only
$ rake db:migrate:engines ENGINE=bar # => raise an exception if 'bar' engine is missing
This patch also supports mixed migrations versioning, this means you can use both timestamped and numeric migrations in your plugins.
Example:
db/migrate/20090224121645_create_birds.rb
vendor/plugins/bar/db/migrate/001_create_bars.rb vendor/plugins/foo/db/migrate/20080224121645_create_foos.rb
$ rake db:migrate # => create birds (current tables: birds) $ rake db:migrate:engines # => create from bar and foo (current tables: birds, bars and foos) $ rake db:migrate:engines:down ENGINE=bar # => delete from bar (current tables: birds and foos)
You can also run migrations from engines first, then yours.
$ rake db:migrate:engines # => create from bar and foo (current tables: bars and foos)
$ rake db:migrate # => create birds (current tables: birds, bars and foos)
As you can see running migrations is an “engine atomic” operation, and it makes sense, because engines are pluggedin applications and you want to run all the migrations from a single engine, in order to make it full working.
Now imagine to have the 0.0.1 version of a plugin called ‘foo’ with the following migrations:
vendor/plugins/foo/db/migrate/20080224121645_create_foos.rb
vendor/plugins/foo/db/migrate/20080224121646_create_bars.rb
Your run your migrations, alongside with yours, so you have birds, foos and bars tables.
When the authors will release the 0.0.2, adding a third migration, if you execute db:migrate:engines, only the last migration will be ran, instead of the full suite.
And of course this is a bless if you want to keep up-to-date your plugins.
I created a Lighthouse ticket for this patch, so if you appreciate it, please vote with a +1.
UPDATE 2009-02-28: I completely rewrote the patch, changing its behavior, fixing stuff and adding a version column to schema_migrations.
Two important changes are about db:migrate and test tasks: they both automatically check/run migrations from plugins. This means test suite will be halted if there are pending migrations from plugins.
I also added a lot of new rake tasks (also for migrating from old Rails versions), and a script for rename a plugin.
For a full review, please visit the Lighthouse ticket.
UPDATE 2009-02-28 (2): I extracted the patch into a plugin: plugin_migrations.