Class: HerokuExternalDb::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/heroku_external_db.rb

Overview

Represents an ActiveRecord database configuration to be used in a Heroku app. This configuration consists of at least one environment variable, and possibly several:

  • [PREFIX]_DATABASE_URL - the Heroku-style DATABASE_URL to connect to. Required.

  • [PREFIX]_DATABASE_CA - the filename of a SSL certificate file which will be configured as the :sslca for the database. Useful for encrypted MySQL, e.g.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(env_prefix, configuration_name) ⇒ Configuration

Returns a new instance of Configuration.



43
44
45
46
# File 'lib/heroku_external_db.rb', line 43

def initialize(env_prefix, configuration_name)
  @env_prefix = env_prefix
  @configuration_name = configuration_name
end

Instance Attribute Details

#ca_pathObject

The path in which your SSL CA certificates are stored. By default, this is [Rails app root]/config/ca.



50
51
52
# File 'lib/heroku_external_db.rb', line 50

def ca_path
  @ca_path ||= ca_path_from_rails_root
end

#configuration_nameObject (readonly)

The ActiveRecord configuration that will be set up. Typically this should be the same as your RAILS_ENV environment variable, but some apps may have multiple database connections with different names.



40
41
42
# File 'lib/heroku_external_db.rb', line 40

def configuration_name
  @configuration_name
end

#env_prefixObject (readonly)

Each HerokuExternalDb must have a unique prefix for its environment variables. For example, if the prefix was set to CRAZY, then the database URL would be taken from CRAZY_DATABASE_URL, and the CA filename would be taken from CRAZY_DATABASE_CA, if it existed.

In typical usage, the prefix will be EXTERNAL by default.



35
36
37
# File 'lib/heroku_external_db.rb', line 35

def env_prefix
  @env_prefix
end

Instance Method Details

#db_ca_configuration(ca_filename) ⇒ Object

Returns a partial ActiveRecord configuration hash for the given SSL CA certificate. Checks to make sure the given filename actually exists, and raises an error if it does not.



79
80
81
82
83
84
85
86
87
88
# File 'lib/heroku_external_db.rb', line 79

def db_ca_configuration(ca_filename)
  return {} unless ca_filename

  raise "ca_path for #{ca_filename} cannot be determined from Rails root; please set it explicitly" unless ca_path
  
  ca_filepath = File.join(ca_path, ca_filename)
  raise "CA file #{ca_filepath} does not exist!" unless File.exists?(ca_filepath)

  return { :sslca => ca_filepath }
end

#db_configObject

Returns an ActiveRecord configuration hash based on the environment variables.



91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/heroku_external_db.rb', line 91

def db_config
  @db_config ||= begin 
    raise "ENV['#{env_prefix}_DATABASE_URL'] expected but not found!" unless ENV["#{env_prefix}_DATABASE_URL"]
    config = parse_db_uri(ENV["#{env_prefix}_DATABASE_URL"])

    if ENV["#{env_prefix}_DATABASE_CA"]
      config.merge!(db_ca_configuration(ENV["#{env_prefix}_DATABASE_CA"]))
    end
  
    config
  end
end

#parse_db_uri(db_uri) ⇒ Object

Parse a Heroku-style database URI and return an ActiveRecord configuration hash based on it. Format is as follows:

<adapter>://[<username>[:<password>]]@<host>[:<port>]/<database>


58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/heroku_external_db.rb', line 58

def parse_db_uri(db_uri)
  uri = URI.parse(db_uri)

  db_config = {
    :adapter => uri.scheme,
    :database => uri.path[1..-1],
    :host => uri.host
  }

  if uri.user
    db_config[:username] = uri.user
    db_config[:password] = uri.password if uri.password
  end
  db_config[:port] = uri.port if uri.port

  db_config
end

#setup!Object

Installs an ActiveRecord configuration based on the environment variables, and makes an initial connection to the database. (This flushes out the connection pool if a different connection has already been established, and tests to make sure we can actually connect.)



108
109
110
111
112
# File 'lib/heroku_external_db.rb', line 108

def setup!
  ActiveRecord::Base.configurations[configuration_name] = db_config
  ActiveRecord::Base.establish_connection(configuration_name).connection
  self
end