Skip to content

Instantly share code, notes, and snippets.

@sidonath
Created January 31, 2014 16:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sidonath/8735211 to your computer and use it in GitHub Desktop.
Save sidonath/8735211 to your computer and use it in GitHub Desktop.

Heroku Postgresql credentials retriever

WARNING: be careful what you do with this.

Installation

  • Create a scripts directory in your Rails app root (if it doesn't already exist) and put the script inside

Usage

$ ruby scripts/use_heroku_db.rb

Run the script with to copy credentials from Heroku DB to your "database.yml".

Your previous "database.yml" will be backed up to "config/database.yml.orig". Run the script again to automatically restore your original "database.yml".

Advanced

You can pass an optional remote name if you have multiple Heroku apps. E.g. if you've got "staging" and "production" remotes, you can get staging's DB credentials with:

$ ruby scripts/use_heroku_db.rb staging
#!/usr/bin/env ruby
require 'uri'
require 'pry'
require 'yaml'
require 'pathname'
class HerokuDbCredentials
attr_accessor :connection_uri
def initialize(environment=nil)
command_string = "heroku pg:credentials DATABASE"
if environment
command_string << " --remote #{environment}"
end
connection_data = `#{command_string}`
connection_url_string = connection_data.split.last
self.connection_uri = URI.parse(connection_url_string)
end
def to_hash
{
'development' => {
'adapter' => 'postgresql',
'encoding' => 'unicode',
'pool' => 5,
'database' => connection_uri.path.gsub(/^\//, ''),
'username' => connection_uri.user,
'password' => connection_uri.password,
'host' => connection_uri.host,
'port' => connection_uri.port,
}
}
end
def to_yaml
to_hash.to_yaml
end
end
class RailsRoot < Pathname
def self.new
super(File.expand_path(__FILE__)).join('../..')
end
end
class ConfigManager
attr_accessor :rails_root, :database_yaml, :database_yaml_backup
def initialize
self.rails_root = RailsRoot.new
self.database_yaml = rails_root.join('config', 'database.yml')
self.database_yaml_backup = rails_root.join('config', 'database.yml.orig')
end
def should_restore?
return false unless File.exist?(database_yaml_backup)
!FileUtils.compare_file(database_yaml, database_yaml_backup)
end
def backup_database_yaml
puts "Backing up database.yml"
FileUtils.cp(database_yaml, database_yaml_backup)
end
def restore_database_yaml
return false unless should_restore?
puts "Restoring database.yml from backup"
FileUtils.move(database_yaml_backup, database_yaml)
true
end
def rewrite_database_yaml(config)
puts "Writing Heroku production config to database.yml"
File.open(database_yaml, 'w') do |f|
f.puts config.to_yaml
end
end
end
def main
env = ARGV.shift
cm = ConfigManager.new
return if cm.restore_database_yaml
cm.backup_database_yaml
credentials = HerokuDbCredentials.new(env)
cm.rewrite_database_yaml(credentials)
puts "Run this script again to restore database.yml from config to connect to the local db"
end
main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment