Mule
What is it?
Mule is a database migration tool based on a stand-alone version of Rails Migrations. By default, Mule uses SQL scripts instead of Migrations DSL, so no Ruby coding is required. It supports multi-database environments, including support for existing databases.
You interact with Mule via a series of Rake commands which map almost 1:1 to Rails Migrations commands, so if you are familiar with them you will be right at home, but if not, don't worry -- it's really easy.
These commands give you a simple, yet powerful toolset allowing you to manage database migrations across both development and production environments.
How do I use it?
Prerequisites
Before using Mule, you must set up a Ruby environment on your machine. Follow the instructions at the links for Ruby and RubyGems.
Once you have both Ruby and RubyGems installed, you should install the Ruby database driver for whatever database you are using, for example:
PostgreSQL
$ gem install pg
Installation
Once your Ruby environment is set up, installing Mule is no big deal:
$ gem install dbmule
Next, create a Rakefile
in your project's base directory containing the following lines:
require 'mule_migrations'
MuleMigrations::Tasks.load_tasks
Installation is complete, you are now ready to begin using Mule.
Create a database project
To begin, create a new database project. A database project represents one database in your system. You can do this with one command:
rake mule:new_project db=foo_bar_database
Mule will then create a directory in your project's base directory called whatever you put in for foo_bar_database
above. Inside it will create the basic Mule project structure, which looks like this:
/
db/
migrate/
sql/
seeds/
config.yml
seeds.rb
After the project has been created, you will need to edit the foo_bar_database\db\config.yml
file and enter the correct database connection information for each environment section you require (development, test, production below). You can create an arbitary number of environments, with any names you like:
development:
adapter: postgresql
encoding: unicode
database: foo_bar_database_development
pool: 5
username:
password:
host: localhost
test:
adapter: postgresql
encoding: unicode
database: foo_bar_database_test
pool: 5
username:
password:
host: localhost
production:
adapter: postgresql
encoding: unicode
database: foo_bar_database_production
pool: 5
username: ENV['FOO_BAR_DATABASE_USER']
password: ENV['FOO_BAR_DATABASE_PSWD']
host: ENV['FOO_BAR_DATABASE_HOST']
Changing the current environment
Any command you run will default to the development
environment, but you can specify which environment you want to run using RAILS_ENV:
$ rake mule:migrate db=foo_bar_database RAILS_ENV=production
Enable migrations on an existing database
Sometimes you will need to create a database project for an existing database. To do so, follow the instructions above for creating a project and then run the following command:
$ rake mule:configure_existing_database db=foo_bar_database
This will add an initial database version to your database with the contents of a schema dump, so that it can be recreated in other environments.
Create a migration:
$ rake mule:new_migration db=foo_bar_database name=foo_bar_migration
A migration represents a single change you want to make in the database, such as adding a table, adding a column, creating an index, dropping a column, dropping a database, dropping an index, defining a stored procedure...and so on.
A migration has both an UP and DOWN implementation: UP to make the change and DOWN to undo it. When you call the command above, by default Mule will create two SQL scripts in the foo_bar_database/db/sql
directory. The format of the filenames are:
<timestamp>_<name_of_migration>_up.sql
<timestamp>_<name_of_migration>_down.sql
example: 20130128185251_foo_bar_migration_up.sql
example: 20130128185251_foo_bar_migration_down.sql
These files are plain old SQL files and that's all they should contain.
Using Ruby
If you want to use the ActiveRecord domain-specific language to write your migrations instead of SQL, pass into the command the flag type=ruby
so that the SQL scripts are not generated and then edit both the up and down methods of the file created in the foo_bar_database/db/migrate
directory. The format of the filename is:
<timestamp>_<name_of_migration>.rb
example: 20130128185251_foo_bar_migration.rb
Migrate database to latest version:
$ rake mule:migrate db=foo_bar_database
This command will run any migrations that have not been run on the database.
Migrate database to specific version (up or down depending on current version):
$ rake mule:migrate db=foo_bar_database VERSION=<specific_version_number>
Run a single, specific migration:
$ rake mule:migrate:up db=foo_bar_database VERSION=<specific_version_number>
or
$ rake mule:migrate:down db=foo_bar_database VERSION=<specific_version_number>
Rollback database to the previous version:
$ rake mule:rollback db=foo_bar_database
Rollback database a certain number of steps:
$ rake mule:rollback db=foo_bar_database STEP=<how_many_steps>
Seed database:
$ rake mule:seed db=foo_bar_database
You can create arbitrary SQL files in the foo_bar_database/db/seeds
directory and they will be executed with this command. Specify order by numbering your files. If you want the data to be removed at each call to mule:seed
, then you need to add that logic.
Retrieve database version:
$ rake mule:version db=foo_bar_database
Create database:
$ rake mule:create db=foo_bar_database
Drop database:
$ rake mule:drop db=foo_bar_database
Reset database:
$ rake mule:reset db=foo_bar_database
Dump schema:
$ rake mule:structure:dump db=foo_bar_database
Load schema:
$ rake mule:structure:load db=foo_bar_database
Notes for production:
Database environment variables
The foo_bar_database/db/config.yml
file can contain environment variable accessors:
production:
adapter: postgresql
encoding: unicode
database: foo_bar_database_production
pool: 5
username: ENV['FOO_BAR_USER']
password: ENV['FOO_BAR_PSWD']
host: ENV['FOO_BAR_HOST']
You can use this in production configurations to pass in database configuration during execution of the command:
$ rake mule:migrate db=foo_bar_database RAILS_ENV=production FOO_BAR_USER=<prod_user> FOO_BAR_PSWD=<prod_pswd> FOO_BAR_HOST=<prod_host>
Safeguard for destructive commands
Mule has a safeguard system in place for any foo_bar_database/db/config.yml
environment that contains the word 'production'. If you run any command that is typically destructive in nature (i.e. data could be lost), then it is required that you pass in an additional confirm argument to the command. The confirm argument must contain the database project name:
$ rake mule:rollback confirm=foo_bar_database db=foo_bar_database RAILS_ENV=production