Capistrano series - database migrations

The basic setup of a Slice and deploying an application from your workstation via Capistrano is now completed.

However, there is one thing left that needs an introduction, and that is how to handle database migrations when deploying your app.


Built in

One of the good things about Capistrano is the ability to create tasks and define when those tasks will be executed. We saw how to do that during the 'deploying application changes' article (see here).

However, there are also a lot built in tasks that are often overlooked or simply not really known about.

Have a look at what's available (remember this is on the workstation, not the Slice):

cap -T

among the outputted tasks are these two:

cap deploy:migrate         # Run the migrate rake task.
cap deploy:migrations    # Deploy and run pending migrations.

Looks just the job for deployment any database migrations.

To view the tasks in more detail, try the the following:

cap -e deploy:migrate

and:

cap -e deploy:migrations

I won't paste it here, but you will see a detailed explanation of what each task does.

Example

Using the example application we have been working on, let's create a simple database migration on the workstation.

ruby script/generate migration Users name:string address:text -c

Note this may not be the best way of creating a database and also note we have no controller or model - it is simply an example that shows the process.

The output of the command is as follows:

create  db/migrate
A         /Users/onion/dev/project1/db/migrate
      create  db/migrate/001_users.rb
A         /Users/onion/dev/project1/db/migrate/001_users.rb

Nothing unusual in that.

It created the db/migrate folder and the 001_users.rb file and, due to using the '-c' suffix, automatically added the new content to subversion.

Migrate

As we are working on our workstation, let's go ahead and migrate the file:

rake db:migrate

Again, a normal routine for migrating the database.

Deploy

We know that a 'normal' change would be deployed using Capistrano with a simple:

cap deploy

However, in this instance we have a special case as we have migrations to deploy.

Using the information from above, we can see this is conducted using:

cap deploy:migrations

In the output will be a line similar to this:

* executing "cd /home/demo/public_html/domain.com/releases/20080129144308;
   rake RAILS_ENV=production  db:migrate"

Well, that's what we wanted to happen.

It even knew that the deployment would need to be a production environment and not a development environment (you can change this default behaviour, see 'cap -e deploy:migrate' for more details).

Releases

There is something that hasn't happened however. Log into the Slice and navigate to the releases folder.

Notice anything?

That's right, there are 6 releases folders. The 'cleanup' task (which we defined in the previous article) hasn't been executed.

There's a very good reason for this. The 'after' task was defined like this:

after "deploy", "deploy:cleanup"

However, we didn't use the 'cap deploy' command, we used the 'cap deploy:migrations' command.

Easy to remedy by adding a supplemental task to the end of the deploy.rb file:

after "deploy:migrations", "deploy:cleanup"

The next time you deploy your migrations, the cleanup task will run and leave you with the current release and the previous four releases, deleting the older ones.

Summary

Many Capistrano tasks are already built in and it is not often you need to create one of your own.

Using 'cap -T' shows many of the available tasks and a 'cap -e xxxxx' will give a detailed description.

As shown, Capistrano handles database migrations smoothly and efficiently.

PickledOnion.

Want to comment?


(not made public)

(optional)

(use plain text or Markdown syntax)