heroku_external_db 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "shoulda", ">= 0"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.5.2"
12
+ gem "rspec", ">= 2.4.0"
13
+ gem "rcov"
14
+ gem "mocha"
15
+ gem "rails", "~> 3.0.0"
16
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,96 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ abstract (1.0.0)
5
+ actionmailer (3.0.1)
6
+ actionpack (= 3.0.1)
7
+ mail (~> 2.2.5)
8
+ actionpack (3.0.1)
9
+ activemodel (= 3.0.1)
10
+ activesupport (= 3.0.1)
11
+ builder (~> 2.1.2)
12
+ erubis (~> 2.6.6)
13
+ i18n (~> 0.4.1)
14
+ rack (~> 1.2.1)
15
+ rack-mount (~> 0.6.12)
16
+ rack-test (~> 0.5.4)
17
+ tzinfo (~> 0.3.23)
18
+ activemodel (3.0.1)
19
+ activesupport (= 3.0.1)
20
+ builder (~> 2.1.2)
21
+ i18n (~> 0.4.1)
22
+ activerecord (3.0.1)
23
+ activemodel (= 3.0.1)
24
+ activesupport (= 3.0.1)
25
+ arel (~> 1.0.0)
26
+ tzinfo (~> 0.3.23)
27
+ activeresource (3.0.1)
28
+ activemodel (= 3.0.1)
29
+ activesupport (= 3.0.1)
30
+ activesupport (3.0.1)
31
+ arel (1.0.1)
32
+ activesupport (~> 3.0.0)
33
+ builder (2.1.2)
34
+ diff-lcs (1.1.2)
35
+ erubis (2.6.6)
36
+ abstract (>= 1.0.0)
37
+ git (1.2.5)
38
+ i18n (0.4.2)
39
+ jeweler (1.5.2)
40
+ bundler (~> 1.0.0)
41
+ git (>= 1.2.5)
42
+ rake
43
+ mail (2.2.15)
44
+ activesupport (>= 2.3.6)
45
+ i18n (>= 0.4.0)
46
+ mime-types (~> 1.16)
47
+ treetop (~> 1.4.8)
48
+ mime-types (1.16)
49
+ mocha (0.9.10)
50
+ rake
51
+ polyglot (0.3.1)
52
+ rack (1.2.1)
53
+ rack-mount (0.6.13)
54
+ rack (>= 1.0.0)
55
+ rack-test (0.5.7)
56
+ rack (>= 1.0)
57
+ rails (3.0.1)
58
+ actionmailer (= 3.0.1)
59
+ actionpack (= 3.0.1)
60
+ activerecord (= 3.0.1)
61
+ activeresource (= 3.0.1)
62
+ activesupport (= 3.0.1)
63
+ bundler (~> 1.0.0)
64
+ railties (= 3.0.1)
65
+ railties (3.0.1)
66
+ actionpack (= 3.0.1)
67
+ activesupport (= 3.0.1)
68
+ rake (>= 0.8.4)
69
+ thor (~> 0.14.0)
70
+ rake (0.8.7)
71
+ rcov (0.9.9)
72
+ rspec (2.4.0)
73
+ rspec-core (~> 2.4.0)
74
+ rspec-expectations (~> 2.4.0)
75
+ rspec-mocks (~> 2.4.0)
76
+ rspec-core (2.4.0)
77
+ rspec-expectations (2.4.0)
78
+ diff-lcs (~> 1.1.2)
79
+ rspec-mocks (2.4.0)
80
+ shoulda (2.11.3)
81
+ thor (0.14.6)
82
+ treetop (1.4.9)
83
+ polyglot (>= 0.3.1)
84
+ tzinfo (0.3.24)
85
+
86
+ PLATFORMS
87
+ ruby
88
+
89
+ DEPENDENCIES
90
+ bundler (~> 1.0.0)
91
+ jeweler (~> 1.5.2)
92
+ mocha
93
+ rails (~> 3.0.0)
94
+ rcov
95
+ rspec (>= 2.4.0)
96
+ shoulda
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Nat Budin
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,36 @@
1
+ = heroku_external_db
2
+
3
+ Allows you to easily set up one or more external databases in Rails applications from Heroku, including the ability to do MySQL connections over SSL. This is useful in the following situations, for example:
4
+
5
+ * Your app connects to multiple databases using differently-named ActiveRecord connections.
6
+ * You want to share a database between applications and aren't on the Heroku dedicated database plan.
7
+ * You want to host your application database somewhere besides Heroku, and run the app using Heroku dynos.
8
+
9
+ == Usage
10
+
11
+ Add the following to your Gemfile:
12
+
13
+ gem 'heroku_external_db'
14
+
15
+ Then run:
16
+
17
+ bundle install
18
+ rails generate heroku_external_db # or script/generate if you're on Rails 2
19
+
20
+ This will set up a default initializer in your app's config/initializers/heroku_external_db.rb. This makes the assumption that you're happy with using EXTERNAL_DATABASE_URL and (optionally) EXTERNAL_DATABASE_CA as your environment variables and that you want to use the external database as your main production DB. If that's not true, please edit the initializer as needed.
21
+
22
+ == Contributing to heroku_external_db
23
+
24
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
25
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
26
+ * Fork the project
27
+ * Start a feature/bugfix branch
28
+ * Commit and push until you are happy with your contribution
29
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
30
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
31
+
32
+ == Copyright
33
+
34
+ Copyright (c) 2011 Nat Budin. See LICENSE.txt for
35
+ further details.
36
+
data/Rakefile ADDED
@@ -0,0 +1,58 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "heroku_external_db"
16
+ gem.homepage = "http://github.com/nbudin/heroku_external_db"
17
+ gem.license = "MIT"
18
+ gem.summary = %Q{Makes it easy to connect Heroku apps to external databases}
19
+ gem.description = <<-DESC
20
+ heroku_external_db lets you specify multiple databases using Heroku-style DATABASE_URL parameters, wire
21
+ them up to different ActiveRecord configurations, and automatically configure it from the Rails
22
+ environment. It also adds support for the :sslca configuration parameter so you can talk to external
23
+ MySQL servers over SSL.
24
+ DESC
25
+ gem.email = "natbudin@gmail.com"
26
+ gem.authors = ["Nat Budin"]
27
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
28
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
29
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
30
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
31
+ end
32
+ Jeweler::RubygemsDotOrgTasks.new
33
+
34
+ require "rspec/core/rake_task"
35
+ desc "Run all examples"
36
+ RSpec::Core::RakeTask.new(:spec) do |t|
37
+ t.rspec_opts = %w[--color]
38
+ t.verbose = false
39
+ end
40
+
41
+ require 'rcov/rcovtask'
42
+ Rcov::RcovTask.new do |test|
43
+ test.libs << 'spec'
44
+ test.pattern = 'spec/*_spec.rb'
45
+ test.verbose = true
46
+ end
47
+
48
+ task :default => :spec
49
+
50
+ require 'rake/rdoctask'
51
+ Rake::RDocTask.new do |rdoc|
52
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
53
+
54
+ rdoc.rdoc_dir = 'rdoc'
55
+ rdoc.title = "heroku_external_db #{version}"
56
+ rdoc.rdoc_files.include('README*')
57
+ rdoc.rdoc_files.include('lib/**/*.rb')
58
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Set up a default initializer for heroku_external_db in a Rails application.
3
+
4
+ Example:
5
+ rails generate heroku_external_db:install
6
+
7
+ This will create:
8
+ config/initializers/heroku_external_db.rb
@@ -0,0 +1,18 @@
1
+ if defined?(Rails::Generators::Base)
2
+ module HerokuExternalDb
3
+ class Generator < Rails::Generators::Base
4
+ def create_initializer_file
5
+ copy_file "initializer.rb", "config/initializers/heroku_external_db.rb"
6
+ end
7
+ end
8
+ end
9
+ else
10
+ class HerokuExternalDbGenerator < Rails::Generator::Base
11
+ def manifest
12
+ record do |m|
13
+ m.directory('config/initializers')
14
+ m.file('initializer.rb', "config/initializers/heroku_external_db.rb")
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ if ENV['EXTERNAL_DATABASE_URL']
2
+ # If you have additional databases aside from the main app database, add setup_configuration!
3
+ # lines for them here. For example, if you have a "users" database configured in
4
+ # USERS_DATABASE_URI, add:
5
+ #
6
+ # HerokuExternalDb.setup_configuration!("USERS", "users")
7
+ #
8
+ # You would then be able to connect to it like so:
9
+ # class User < ActiveRecord::Base
10
+ # establish_connection :users
11
+ # end
12
+
13
+ # This has to come last so that it will be the default ActiveRecord configuration.
14
+ HerokuExternalDb.setup_rails_env!
15
+ end
@@ -0,0 +1,81 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{heroku_external_db}
8
+ s.version = "1.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Nat Budin"]
12
+ s.date = %q{2011-02-01}
13
+ s.description = %q{ heroku_external_db lets you specify multiple databases using Heroku-style DATABASE_URL parameters, wire
14
+ them up to different ActiveRecord configurations, and automatically configure it from the Rails
15
+ environment. It also adds support for the :sslca configuration parameter so you can talk to external
16
+ MySQL servers over SSL.
17
+ }
18
+ s.email = %q{natbudin@gmail.com}
19
+ s.extra_rdoc_files = [
20
+ "LICENSE.txt",
21
+ "README.rdoc"
22
+ ]
23
+ s.files = [
24
+ ".document",
25
+ "Gemfile",
26
+ "Gemfile.lock",
27
+ "LICENSE.txt",
28
+ "README.rdoc",
29
+ "Rakefile",
30
+ "VERSION",
31
+ "generators/heroku_external_db/USAGE",
32
+ "generators/heroku_external_db/heroku_external_db_generator.rb",
33
+ "generators/heroku_external_db/templates/initializer.rb",
34
+ "heroku_external_db.gemspec",
35
+ "init.rb",
36
+ "lib/heroku_external_db.rb",
37
+ "rails/init.rb",
38
+ "spec/heroku_external_db_spec.rb",
39
+ "spec/spec_helper.rb"
40
+ ]
41
+ s.homepage = %q{http://github.com/nbudin/heroku_external_db}
42
+ s.licenses = ["MIT"]
43
+ s.require_paths = ["lib"]
44
+ s.rubygems_version = %q{1.5.0}
45
+ s.summary = %q{Makes it easy to connect Heroku apps to external databases}
46
+ s.test_files = [
47
+ "spec/heroku_external_db_spec.rb",
48
+ "spec/spec_helper.rb"
49
+ ]
50
+
51
+ if s.respond_to? :specification_version then
52
+ s.specification_version = 3
53
+
54
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
55
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
56
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
57
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
58
+ s.add_development_dependency(%q<rspec>, [">= 2.4.0"])
59
+ s.add_development_dependency(%q<rcov>, [">= 0"])
60
+ s.add_development_dependency(%q<mocha>, [">= 0"])
61
+ s.add_development_dependency(%q<rails>, ["~> 3.0.0"])
62
+ else
63
+ s.add_dependency(%q<shoulda>, [">= 0"])
64
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
65
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
66
+ s.add_dependency(%q<rspec>, [">= 2.4.0"])
67
+ s.add_dependency(%q<rcov>, [">= 0"])
68
+ s.add_dependency(%q<mocha>, [">= 0"])
69
+ s.add_dependency(%q<rails>, ["~> 3.0.0"])
70
+ end
71
+ else
72
+ s.add_dependency(%q<shoulda>, [">= 0"])
73
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
74
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
75
+ s.add_dependency(%q<rspec>, [">= 2.4.0"])
76
+ s.add_dependency(%q<rcov>, [">= 0"])
77
+ s.add_dependency(%q<mocha>, [">= 0"])
78
+ s.add_dependency(%q<rails>, ["~> 3.0.0"])
79
+ end
80
+ end
81
+
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ # nothing
@@ -0,0 +1,121 @@
1
+ module HerokuExternalDb
2
+ # Construct a new HerokuExternalDb instance based on the given env_prefix and
3
+ # configuration_name, then install the configuration in ActiveRecord. Returns
4
+ # the new instance.
5
+ def self.setup_configuration!(env_prefix, configuration_name)
6
+ HerokuExternalDb::Configuration.new(env_prefix, configuration_name).setup!
7
+ end
8
+
9
+ # Construct a HerokuExternalDb instance for the current Rails environment, then
10
+ # install the configuration in ActiveRecord. You can optionally override the
11
+ # environment variable prefix, which is +EXTERNAL+ by default. Returns the new
12
+ # instance.
13
+ #
14
+ # Note that doing this causes DATABASE_URL to be effectively ignored.
15
+ def self.setup_rails_env!(env_prefix='EXTERNAL')
16
+ raise "ENV['RAILS_ENV'] is not set" unless ENV['RAILS_ENV']
17
+ setup_configuration!(env_prefix, ENV['RAILS_ENV'])
18
+ end
19
+
20
+ # Represents an ActiveRecord database configuration to be used in a Heroku app.
21
+ # This configuration consists of at least one environment variable, and possibly
22
+ # several:
23
+ #
24
+ # * +[PREFIX]_DATABASE_URL+ - the Heroku-style DATABASE_URL to connect to. Required.
25
+ # * +[PREFIX]_DATABASE_CA+ - the filename of a SSL certificate file which will be
26
+ # configured as the :sslca for the database. Useful for encrypted MySQL, e.g.
27
+ class Configuration
28
+
29
+ # Each HerokuExternalDb must have a unique prefix for its environment variables.
30
+ # For example, if the prefix was set to +CRAZY+, then the database URL would be
31
+ # taken from +CRAZY_DATABASE_URL+, and the CA filename would be taken from
32
+ # +CRAZY_DATABASE_CA+, if it existed.
33
+ #
34
+ # In typical usage, the prefix will be +EXTERNAL+ by default.
35
+ attr_reader :env_prefix
36
+
37
+ # The ActiveRecord configuration that will be set up. Typically this should be
38
+ # the same as your +RAILS_ENV+ environment variable, but some apps may have
39
+ # multiple database connections with different names.
40
+ attr_reader :configuration_name
41
+ attr_writer :ca_path
42
+
43
+ def initialize(env_prefix, configuration_name)
44
+ @env_prefix = env_prefix
45
+ @configuration_name = configuration_name
46
+ end
47
+
48
+ # The path in which your SSL CA certificates are stored. By default, this is
49
+ # +[Rails app root]/config/ca+.
50
+ def ca_path
51
+ @ca_path ||= ca_path_from_rails_root
52
+ end
53
+
54
+ # Parse a Heroku-style database URI and return an ActiveRecord configuration hash
55
+ # based on it. Format is as follows:
56
+ #
57
+ # <adapter>://[<username>[:<password>]]@<host>[:<port>]/<database>
58
+ def parse_db_uri(db_uri)
59
+ uri = URI.parse(db_uri)
60
+
61
+ db_config = {
62
+ :adapter => uri.scheme,
63
+ :database => uri.path[1..-1],
64
+ :host => uri.host
65
+ }
66
+
67
+ if uri.user
68
+ db_config[:username] = uri.user
69
+ db_config[:password] = uri.password if uri.password
70
+ end
71
+ db_config[:port] = uri.port if uri.port
72
+
73
+ db_config
74
+ end
75
+
76
+ # Returns a partial ActiveRecord configuration hash for the given SSL CA certificate.
77
+ # Checks to make sure the given filename actually exists, and raises an error if it
78
+ # does not.
79
+ def db_ca_configuration(ca_filename)
80
+ return {} unless ca_filename
81
+
82
+ raise "ca_path for #{ca_filename} cannot be determined from Rails root; please set it explicitly" unless ca_path
83
+
84
+ ca_filepath = File.join(ca_path, ca_filename)
85
+ raise "CA file #{ca_filepath} does not exist!" unless File.exists?(ca_filepath)
86
+
87
+ return { :sslca => ca_filepath }
88
+ end
89
+
90
+ # Returns an ActiveRecord configuration hash based on the environment variables.
91
+ def db_config
92
+ @db_config ||= begin
93
+ raise "ENV['#{env_prefix}_DATABASE_URL'] expected but not found!" unless ENV["#{env_prefix}_DATABASE_URL"]
94
+ config = parse_db_uri(ENV["#{env_prefix}_DATABASE_URL"])
95
+
96
+ if ENV["#{env_prefix}_DATABASE_CA"]
97
+ config.merge!(db_ca_configuration(ENV["#{env_prefix}_DATABASE_CA"]))
98
+ end
99
+
100
+ config
101
+ end
102
+ end
103
+
104
+ # Installs an ActiveRecord configuration based on the environment variables, and
105
+ # makes an initial connection to the database. (This flushes out the connection
106
+ # pool if a different connection has already been established, and tests to
107
+ # make sure we can actually connect.)
108
+ def setup!
109
+ ActiveRecord::Base.configurations[configuration_name] = db_config
110
+ ActiveRecord::Base.establish_connection(configuration_name).connection
111
+ self
112
+ end
113
+
114
+ protected
115
+ def ca_path_from_rails_root
116
+ if defined?(Rails) && Rails.respond_to?(:root) && Rails.root
117
+ File.join(Rails.root, 'config', 'ca')
118
+ end
119
+ end
120
+ end
121
+ end
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ # nothing
@@ -0,0 +1,233 @@
1
+ require 'spec_helper'
2
+ require 'tempfile'
3
+
4
+ COMPLETE_DB_URL = "magicdb://joe:secure@db.example.com:12345/super_special_database"
5
+ COMPLETE_DB_CONFIG = {
6
+ :adapter => "magicdb",
7
+ :username => "joe",
8
+ :password => "secure",
9
+ :host => "db.example.com",
10
+ :port => 12345,
11
+ :database => "super_special_database"
12
+ }
13
+
14
+ def setup_ca_cert(extdb)
15
+ @cert_path = Tempfile.new("mykey.pem").path
16
+ extdb.ca_path, @cert_filename = File.split(@cert_path)
17
+
18
+ return @cert_path, @cert_filename
19
+ end
20
+
21
+ describe HerokuExternalDb::Configuration do
22
+ before do
23
+ @extdb = HerokuExternalDb::Configuration.new("GREEN", "red")
24
+ end
25
+
26
+ it "initializes based on env_prefix and configuration_name" do
27
+ @extdb.env_prefix.should == "GREEN"
28
+ @extdb.configuration_name.should == "red"
29
+ end
30
+
31
+ describe "#ca_path" do
32
+ it "should return nil if Rails.root is not available" do
33
+ @extdb.ca_path.should be_nil
34
+ end
35
+
36
+ it "should figure out CA path based on Rails root" do
37
+ Rails.expects(:root).at_least_once.returns("/my/rails/app")
38
+ @extdb.ca_path.should == "/my/rails/app/config/ca"
39
+ end
40
+
41
+ it "should allow override" do
42
+ @extdb.ca_path = "/other/rails/app/config/ca"
43
+ @extdb.ca_path.should == "/other/rails/app/config/ca"
44
+ end
45
+ end
46
+
47
+ describe "#parse_db_uri" do
48
+ context "with minimal URI" do
49
+ before do
50
+ @config = @extdb.parse_db_uri("hyperdb://localhost/loco")
51
+ end
52
+
53
+ it "should leave unspecified parts as nil" do
54
+ %w{username password port}.each do |key|
55
+ @config.has_key?(key.to_sym).should be_false
56
+ end
57
+
58
+ %w{adapter host database}.each do |key|
59
+ @config.has_key?(key.to_sym).should be_true
60
+ end
61
+ end
62
+ end
63
+
64
+ context "with complete URI" do
65
+ before do
66
+ @config = @extdb.parse_db_uri(COMPLETE_DB_URL)
67
+ end
68
+
69
+ it "should parse all parts of the URI" do
70
+ COMPLETE_DB_CONFIG.each do |key, value|
71
+ @config[key].should == value
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ describe "#db_ca_configuration" do
78
+ context "with a CA path" do
79
+ before do
80
+ @cert_path, @cert_filename = setup_ca_cert(@extdb)
81
+ end
82
+
83
+ it "should return an empty hash if not given a filename" do
84
+ @extdb.db_ca_configuration(nil).should == {}
85
+ end
86
+
87
+ it "should have the correct pathname to the CA cert" do
88
+ @config = @extdb.db_ca_configuration(@cert_filename)
89
+ @config[:sslca].should == @cert_path
90
+ end
91
+
92
+ it "should throw an error if the file doesn't exist" do
93
+ File.delete(@cert_path)
94
+ lambda { @extdb.db_ca_configuration(@cert_filename) }.should raise_error
95
+ end
96
+
97
+ after do
98
+ File.delete(@cert_path) if File.exist?(@cert_path)
99
+ end
100
+ end
101
+
102
+ context "without a CA path" do
103
+ it "should return an empty hash if not given a filename" do
104
+ @extdb.db_ca_configuration(nil).should == {}
105
+ end
106
+
107
+ it "should raise an error if given a filename" do
108
+ lambda { @extdb.db_ca_configuration("filename") }.should raise_error
109
+ end
110
+ end
111
+ end
112
+
113
+ describe "#db_config" do
114
+ context "with database URL" do
115
+ before do
116
+ ENV['GREEN_DATABASE_URL'] = COMPLETE_DB_URL
117
+ end
118
+
119
+ it "should parse the URL path from the environment" do
120
+ @config = @extdb.db_config
121
+
122
+ COMPLETE_DB_CONFIG.each do |key, value|
123
+ @config[key].should == value
124
+ end
125
+ end
126
+
127
+ context "with CA" do
128
+ before do
129
+ @cert_path, @cert_filename = setup_ca_cert(@extdb)
130
+ ENV['GREEN_DATABASE_CA'] = @cert_filename
131
+ end
132
+
133
+ it "should parse the CA path from the environment" do
134
+ @config = @extdb.db_config
135
+ @config[:sslca].should == @cert_path
136
+ end
137
+
138
+ after do
139
+ File.delete(@cert_path)
140
+ ENV.delete('GREEN_DATABASE_CA')
141
+ end
142
+ end
143
+
144
+ after do
145
+ ENV.delete('GREEN_DATABASE_URL')
146
+ end
147
+ end
148
+
149
+ context "without database URL" do
150
+ it "should raise an error" do
151
+ lambda { @extdb.db_config }.should raise_error
152
+ end
153
+ end
154
+ end
155
+
156
+ context "with mock green/red database objects" do
157
+ before do
158
+ ENV["GREEN_DATABASE_URL"] = COMPLETE_DB_URL
159
+ @mock_pool = mock()
160
+ @mock_pool.expects(:connection).at_least_once
161
+ ActiveRecord::Base.expects(:establish_connection).with("red").at_least_once.returns(@mock_pool)
162
+ end
163
+
164
+ describe "#setup!" do
165
+ it "should return self" do
166
+ @extdb.setup!.should equal(@extdb)
167
+ end
168
+ end
169
+
170
+ describe ".setup_configuration!" do
171
+ it "should return a new instance" do
172
+ @new_extdb = HerokuExternalDb.setup_configuration!("GREEN", "red")
173
+ @new_extdb.should be_instance_of(HerokuExternalDb::Configuration)
174
+ @new_extdb.should_not equal(@extdb)
175
+ end
176
+ end
177
+
178
+ after do
179
+ ENV.delete("GREEN_DATABASE_URL")
180
+ end
181
+ end
182
+
183
+ describe ".setup_rails_env!" do
184
+ before do
185
+ ENV['EXTERNAL_DATABASE_URL'] = COMPLETE_DB_URL
186
+ end
187
+
188
+ context "without a RAILS_ENV" do
189
+ it "should raise an error" do
190
+ lambda { HerokuExternalDb.setup_rails_env! }.should raise_error
191
+ lambda { HerokuExternalDb.setup_rails_env!("PURPLE") }.should raise_error
192
+ end
193
+ end
194
+
195
+ context "with a RAILS_ENV" do
196
+ before do
197
+ ENV['RAILS_ENV'] = "yummy"
198
+ @mock_pool = mock()
199
+ @mock_pool.expects(:connection).at_least_once
200
+ ActiveRecord::Base.expects(:establish_connection).with("yummy").at_least_once.returns(@mock_pool)
201
+ end
202
+
203
+ it "should return a new instance based on RAILS_ENV" do
204
+ @new_extdb = HerokuExternalDb.setup_rails_env!
205
+ @new_extdb.should be_instance_of(HerokuExternalDb::Configuration)
206
+ @new_extdb.should_not equal(@extdb)
207
+ end
208
+
209
+ context "with the orange DB URL in env" do
210
+ before do
211
+ ENV['ORANGE_DATABASE_URL'] = "mysql://db.example.org/orange"
212
+ end
213
+
214
+ it "should allow specifying a different env_prefix" do
215
+ @orange_extdb = HerokuExternalDb.setup_rails_env!("ORANGE")
216
+ ActiveRecord::Base.configurations["yummy"][:database].should == "orange"
217
+ end
218
+
219
+ after do
220
+ ENV.delete("ORANGE_DATABASE_URL")
221
+ end
222
+ end
223
+
224
+ after do
225
+ ENV.delete('RAILS_ENV')
226
+ end
227
+ end
228
+
229
+ after do
230
+ ENV.delete("EXTERNAL_DATABASE_URL")
231
+ end
232
+ end
233
+ end
@@ -0,0 +1,10 @@
1
+ require 'rspec'
2
+ require 'rails'
3
+ require 'active_record'
4
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'heroku_external_db')
5
+
6
+
7
+ Rspec.configure do |c|
8
+ c.mock_with :mocha
9
+ end
10
+
metadata ADDED
@@ -0,0 +1,189 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: heroku_external_db
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Nat Budin
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-28 00:00:00 -05:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ prerelease: false
23
+ type: :development
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ name: shoulda
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ prerelease: false
37
+ type: :development
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ hash: 23
44
+ segments:
45
+ - 1
46
+ - 0
47
+ - 0
48
+ version: 1.0.0
49
+ name: bundler
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ prerelease: false
53
+ type: :development
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ~>
58
+ - !ruby/object:Gem::Version
59
+ hash: 7
60
+ segments:
61
+ - 1
62
+ - 5
63
+ - 2
64
+ version: 1.5.2
65
+ name: jeweler
66
+ version_requirements: *id003
67
+ - !ruby/object:Gem::Dependency
68
+ prerelease: false
69
+ type: :development
70
+ requirement: &id004 !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ hash: 31
76
+ segments:
77
+ - 2
78
+ - 4
79
+ - 0
80
+ version: 2.4.0
81
+ name: rspec
82
+ version_requirements: *id004
83
+ - !ruby/object:Gem::Dependency
84
+ prerelease: false
85
+ type: :development
86
+ requirement: &id005 !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ hash: 3
92
+ segments:
93
+ - 0
94
+ version: "0"
95
+ name: rcov
96
+ version_requirements: *id005
97
+ - !ruby/object:Gem::Dependency
98
+ prerelease: false
99
+ type: :development
100
+ requirement: &id006 !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ hash: 3
106
+ segments:
107
+ - 0
108
+ version: "0"
109
+ name: mocha
110
+ version_requirements: *id006
111
+ - !ruby/object:Gem::Dependency
112
+ prerelease: false
113
+ type: :development
114
+ requirement: &id007 !ruby/object:Gem::Requirement
115
+ none: false
116
+ requirements:
117
+ - - ~>
118
+ - !ruby/object:Gem::Version
119
+ hash: 7
120
+ segments:
121
+ - 3
122
+ - 0
123
+ - 0
124
+ version: 3.0.0
125
+ name: rails
126
+ version_requirements: *id007
127
+ description: " heroku_external_db lets you specify multiple databases using Heroku-style DATABASE_URL parameters, wire\n them up to different ActiveRecord configurations, and automatically configure it from the Rails\n environment. It also adds support for the :sslca configuration parameter so you can talk to external\n MySQL servers over SSL.\n"
128
+ email: natbudin@gmail.com
129
+ executables: []
130
+
131
+ extensions: []
132
+
133
+ extra_rdoc_files:
134
+ - LICENSE.txt
135
+ - README.rdoc
136
+ files:
137
+ - .document
138
+ - Gemfile
139
+ - Gemfile.lock
140
+ - LICENSE.txt
141
+ - README.rdoc
142
+ - Rakefile
143
+ - VERSION
144
+ - generators/heroku_external_db/USAGE
145
+ - generators/heroku_external_db/heroku_external_db_generator.rb
146
+ - generators/heroku_external_db/templates/initializer.rb
147
+ - heroku_external_db.gemspec
148
+ - init.rb
149
+ - lib/heroku_external_db.rb
150
+ - rails/init.rb
151
+ - spec/heroku_external_db_spec.rb
152
+ - spec/spec_helper.rb
153
+ has_rdoc: true
154
+ homepage: http://github.com/nbudin/heroku_external_db
155
+ licenses:
156
+ - MIT
157
+ post_install_message:
158
+ rdoc_options: []
159
+
160
+ require_paths:
161
+ - lib
162
+ required_ruby_version: !ruby/object:Gem::Requirement
163
+ none: false
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ hash: 3
168
+ segments:
169
+ - 0
170
+ version: "0"
171
+ required_rubygems_version: !ruby/object:Gem::Requirement
172
+ none: false
173
+ requirements:
174
+ - - ">="
175
+ - !ruby/object:Gem::Version
176
+ hash: 3
177
+ segments:
178
+ - 0
179
+ version: "0"
180
+ requirements: []
181
+
182
+ rubyforge_project:
183
+ rubygems_version: 1.5.0
184
+ signing_key:
185
+ specification_version: 3
186
+ summary: Makes it easy to connect Heroku apps to external databases
187
+ test_files:
188
+ - spec/heroku_external_db_spec.rb
189
+ - spec/spec_helper.rb