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.
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):
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
cap -e deploy:migrations
I won't paste it here, but you will see a detailed explanation of what each task does.
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.
As we are working on our workstation, let's go ahead and migrate the file:
Again, a normal routine for migrating the database.
We know that a 'normal' change would be deployed using Capistrano with a simple:
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:
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).
There is something that hasn't happened however. Log into the Slice and navigate to the releases folder.
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.
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.