Skip to content

Instantly share code, notes, and snippets.

@hashrocketeer
Created February 12, 2013 17:48
Show Gist options
  • Save hashrocketeer/4771695 to your computer and use it in GitHub Desktop.
Save hashrocketeer/4771695 to your computer and use it in GitHub Desktop.
Clone task for heroku databases
# tasks for working with your heroku database
#
# Examples:
#
# Replace development DB with a fresh capture from Heroku
# (removing the oldest one first)
#
# rake hdb:clone # replace development database with a fresh capture of the
# heroku database
#
# choose a different local:
# RAILS_ENV=production rake hdb:clone
#
# choose a different remote:
# HEROKU_APP=the-production-app-name rake hdb:clone
namespace :hdb do
def hdbconfig
env = ENV.fetch 'RAILS_ENV', 'development'
@hdbconfig ||= ActiveRecord::Base.configurations[env]
end
task(ensure_dropped: 'db:load_config') { drop_database hdbconfig }
task(create_one: 'db:load_config') { create_database hdbconfig }
desc "replace the RAILS_ENV database with a fresh capture from HEROKU_APP"
task clone: [:ensure_dropped, :create_one] do
env = ENV.fetch 'RAILS_ENV', 'development'
HerokuDB.capture_and_restore(env)
end
end
class HerokuDB
def self.capture_and_restore(env)
db = new(env)
db.capture
db.restore
end
attr_reader :environment
def initialize(env)
@environment = env
end
def capture
pgbackup 'capture --expire'
end
def restore
print_and_capture %(curl "#{url}" | pg_restore --no-acl --no-owner #{username} -d #{database})
end
private
def url
pgbackup(:url).chomp
end
def username
if config['username']
"-U #{config['username']}"
end
end
def database
config['database']
end
def config
@config ||= ActiveRecord::Base.configurations[environment]
end
def pgbackup(task=nil)
sub_command = task ? "pgbackups:#{task}" : 'pgbackups'
print_and_capture "heroku #{sub_command} #{heroku_app}"
end
def heroku_app
return @heroku_app if defined?(@heroku_app)
@heroku_app = determine_heroku_app
end
def determine_heroku_app
if ENV['HEROKU_APP']
return "--app #{ENV['HEROKU_APP']}"
end
remotes = `git remote`.chomp.split("\n")
remote = %w(heroku production staging heroku-production heroku-staging).detect do |remote|
remotes.include?(remote)
end
"--remote #{remote}" if remote
end
def print_and_capture(command)
puts command
output = `#{command}`
exit "non-zero exit status!" if $?.exitstatus != 0
output
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment