Capistrano Task to Load Production Data «

Comments Off on Capistrano Task to Load Production Data

I was working on a migration that had a decent chance of messing up my database and wanted assurance it would work with production data, not just my fixtures.

Building on Bojan Mihelac’s code to download files, I wrote a Capistrano task to load the production database into my local database. And then capistrano 1.4.0 was released with a built-in get method for downloading files. So if you have 1.4.0, you can just throw away that whole function.

# Get file remote_path from FIRST server targetted by
# the current task and transfer it to local machine as path, SFTP required
def actor.get(remote_path, path, options = {})
execute_on_servers(options) do |servers|
self.sessions[servers.first].sftp.connect do |tsftp| "Get #{remote_path} to #{path}"
tsftp.get_file remote_path, path

desc "Load production data into development database"
task :load_production_data, :roles => :db, :only => { :primary => true } do
require 'yaml'

database = YAML::load_file('config/database.yml')

filename = "dump.#{ '%Y-%m-%d_%H:%M:%S'}.sql"
on_rollback { delete "/tmp/#{filename}" }

run "mysqldump -u #{database['production']['username']} --password=#{database['production']['password']} #{database['production']['database']} > /tmp/#{filename}" do |channel, stream, data|
puts data
get "/tmp/#{filename}", filename
exec "/tmp/#{filename}"
exec "mysql -u #{database['development']['username']} --password=#{database['development']['password']} #{database['development']['database']} < #{filename}; rm -f #{filename}" end

After adding the code to the tail of my config/deploy.rb, I ran cap load_production_data. Then I had a full copy of the production database to tinker with until I was content my migration was flawless.

Production data is also useful for other things. I can run complicated stats queries without worrying about bogging down the site, and see layout bugs that don't happen unless there's a few dozen tags on the page.