activerecord_url_connections 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +6 -1
- data/Rakefile +13 -1
- data/Readme.md +68 -0
- data/activerecord_url_connections.gemspec +1 -0
- data/lib/activerecord_url_connections.rb +31 -0
- data/lib/activerecord_url_connections/version.rb +1 -1
- data/test/connection_test.rb +93 -0
- metadata +18 -12
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -1,2 +1,14 @@
|
|
1
|
-
require
|
1
|
+
require "bundler"
|
2
|
+
require "rake"
|
3
|
+
require "rake/testtask"
|
4
|
+
module ActiveRecordURLConnections
|
5
|
+
class RakeTasks
|
6
|
+
include Rake::DSL
|
7
|
+
Rake::TestTask.new do |t|
|
8
|
+
t.libs << "test"
|
9
|
+
t.test_files = FileList["test/*_test.rb"]
|
10
|
+
t.verbose = true
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
2
14
|
Bundler::GemHelper.install_tasks
|
data/Readme.md
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# ActiveRecord URL Connections
|
2
|
+
|
3
|
+
This gem adds support to ActiveRecord for connecting to a database by
|
4
|
+
specifying a URL rather than a hash of parameters. Many ruby adapters
|
5
|
+
have opted for this format (DataMapper, Sequel, MongoDB, etc.) in
|
6
|
+
addition to numerous alternatives in other languages. So why should AR
|
7
|
+
be missing out on all the fun?
|
8
|
+
|
9
|
+
The other notable benefit is that you can continue to use
|
10
|
+
`config/database.yml` in development, while setting an ENV variable
|
11
|
+
of `DATABASE_URL` on your production server to specify the connection
|
12
|
+
settings. No more risk of committing sensitive database credentials into
|
13
|
+
version control, or having to worry about Capistrano moving the relevant
|
14
|
+
production file into place on deploy.
|
15
|
+
|
16
|
+
## Usage
|
17
|
+
|
18
|
+
The URL takes the form of:
|
19
|
+
|
20
|
+
<adapter>://<user>:<password>@<hostname>:<port>/<database>?<options>
|
21
|
+
|
22
|
+
Where options is a query string of key value pairs. For example:
|
23
|
+
|
24
|
+
mysql://app:s3crets@127.0.0.1:5123/nyancat_production?encoding=utf8
|
25
|
+
|
26
|
+
Only `adapter`, `hostname`, and `database` are required. Everything else
|
27
|
+
is optional, so to connect using local user permissions in postgres just do:
|
28
|
+
|
29
|
+
postgres://localhost/nyancat_production
|
30
|
+
|
31
|
+
## Installation
|
32
|
+
|
33
|
+
Either in your `Gemfile`:
|
34
|
+
|
35
|
+
gem "activerecord_url_connections"
|
36
|
+
|
37
|
+
Or install it directly onto your system with rubygems:
|
38
|
+
|
39
|
+
gem install activerecord_url_connections
|
40
|
+
|
41
|
+
Then require in your app:
|
42
|
+
|
43
|
+
require "activerecord_url_connections"
|
44
|
+
|
45
|
+
## License
|
46
|
+
|
47
|
+
ActiveRecord URL Connections is MIT Licensed
|
48
|
+
|
49
|
+
Copyright (C) 2011 by Glenn Gillen
|
50
|
+
|
51
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
52
|
+
of this software and associated documentation files (the "Software"), to deal
|
53
|
+
in the Software without restriction, including without limitation the rights
|
54
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
55
|
+
copies of the Software, and to permit persons to whom the Software is
|
56
|
+
furnished to do so, subject to the following conditions:
|
57
|
+
|
58
|
+
The above copyright notice and this permission notice shall be included in
|
59
|
+
all copies or substantial portions of the Software.
|
60
|
+
|
61
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
62
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
63
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
64
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
65
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
66
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
67
|
+
SOFTWARE.
|
68
|
+
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require "active_record"
|
1
2
|
module ActiveRecordURLConnections
|
2
3
|
def self.parse(str)
|
3
4
|
config = URI.parse(str)
|
@@ -11,3 +12,33 @@ module ActiveRecordURLConnections
|
|
11
12
|
}
|
12
13
|
end
|
13
14
|
end
|
15
|
+
|
16
|
+
ActiveRecord::Base.class_eval do
|
17
|
+
class << self
|
18
|
+
alias_method :establish_connection_without_url, :establish_connection
|
19
|
+
def establish_connection(spec = nil)
|
20
|
+
spec ||= ENV["DATABASE_URL"]
|
21
|
+
if spec.is_a?(String) && url = URI.parse(spec)
|
22
|
+
adapter = url.scheme
|
23
|
+
adapter = "postgresql" if adapter == "postgres"
|
24
|
+
spec = { :adapter => adapter,
|
25
|
+
:username => url.user,
|
26
|
+
:password => url.password,
|
27
|
+
:database => url.path.sub(%r{^/},""),
|
28
|
+
:port => url.port,
|
29
|
+
:hostname => url.host }
|
30
|
+
spec.reject!{ |key,value| value.nil? }
|
31
|
+
spec.merge!(split_query_options(url.query))
|
32
|
+
end
|
33
|
+
establish_connection_without_url(spec)
|
34
|
+
rescue URI::InvalidURIError
|
35
|
+
establish_connection_without_url(spec)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
def split_query_options(query = nil)
|
40
|
+
return {} unless query
|
41
|
+
Hash[query.split("&").map{ |pair| pair.split("=") }].symbolize_keys
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler/setup"
|
3
|
+
Bundler.require(:test)
|
4
|
+
require "test/unit"
|
5
|
+
require "mocha"
|
6
|
+
require "activerecord_url_connections"
|
7
|
+
class TestConnection < Test::Unit::TestCase
|
8
|
+
def mock_connection_spec(spec, adapter)
|
9
|
+
conn_spec = ActiveRecord::Base::ConnectionSpecification.new(spec, adapter)
|
10
|
+
ActiveRecord::Base::ConnectionSpecification.stubs(:new).
|
11
|
+
with(spec, adapter).returns(conn_spec)
|
12
|
+
conn_spec
|
13
|
+
end
|
14
|
+
|
15
|
+
def setup
|
16
|
+
ActiveRecord::ConnectionAdapters::ConnectionHandler.any_instance.
|
17
|
+
stubs(:establish_connection)
|
18
|
+
end
|
19
|
+
|
20
|
+
def spec_hash(opts = {})
|
21
|
+
default_spec = { :adapter => "mysql",
|
22
|
+
:username => "user",
|
23
|
+
:password => "secret",
|
24
|
+
:hostname => "localhost",
|
25
|
+
:database => "mydatabase" }
|
26
|
+
default_spec.merge!(opts)
|
27
|
+
default_spec
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_generic_url_connection
|
31
|
+
connection_spec = mock_connection_spec(spec_hash, "mysql_connection")
|
32
|
+
url = "mysql://user:secret@localhost/mydatabase"
|
33
|
+
ActiveRecord::ConnectionAdapters::ConnectionHandler.any_instance.
|
34
|
+
expects(:establish_connection).with("ActiveRecord::Base", connection_spec)
|
35
|
+
ActiveRecord::Base.establish_connection(url)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_works_with_traditional_hash_spec
|
39
|
+
spec = spec_hash
|
40
|
+
connection_spec = mock_connection_spec(spec, "mysql_connection")
|
41
|
+
ActiveRecord::ConnectionAdapters::ConnectionHandler.any_instance.
|
42
|
+
expects(:establish_connection).with("ActiveRecord::Base", connection_spec)
|
43
|
+
ActiveRecord::Base.establish_connection(spec)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_doesnt_raise_uri_parse_error
|
47
|
+
url = "this isn't a URL"
|
48
|
+
assert_raises ActiveRecord::AdapterNotSpecified do
|
49
|
+
ActiveRecord::Base.establish_connection(url)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_translates_postgres
|
54
|
+
spec = spec_hash(:adapter => "postgresql")
|
55
|
+
connection_spec = mock_connection_spec(spec, "postgresql_connection")
|
56
|
+
url = "postgres://user:secret@localhost/mydatabase"
|
57
|
+
ActiveRecord::ConnectionAdapters::ConnectionHandler.any_instance.
|
58
|
+
expects(:establish_connection).with("ActiveRecord::Base", connection_spec)
|
59
|
+
ActiveRecord::Base.establish_connection(url)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_supports_additional_options_as_params
|
63
|
+
spec = spec_hash(:encoding => "utf8",
|
64
|
+
:hostname => "remotehost.example.org",
|
65
|
+
:port => 3133,
|
66
|
+
:random_key => "blah")
|
67
|
+
connection_spec = mock_connection_spec(spec, "mysql_connection")
|
68
|
+
url = "mysql://user:secret@remotehost.example.org:3133/mydatabase?encoding=utf8&random_key=blah"
|
69
|
+
ActiveRecord::ConnectionAdapters::ConnectionHandler.any_instance.
|
70
|
+
expects(:establish_connection).with("ActiveRecord::Base", connection_spec)
|
71
|
+
ActiveRecord::Base.establish_connection(url)
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_drops_empty_values_from_spec
|
75
|
+
spec = spec_hash
|
76
|
+
spec.delete(:username)
|
77
|
+
spec.delete(:password)
|
78
|
+
connection_spec = mock_connection_spec(spec, "mysql_connection")
|
79
|
+
url = "mysql://localhost/mydatabase"
|
80
|
+
ActiveRecord::ConnectionAdapters::ConnectionHandler.any_instance.
|
81
|
+
expects(:establish_connection).with("ActiveRecord::Base", connection_spec)
|
82
|
+
ActiveRecord::Base.establish_connection(url)
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_use_environment_variable_if_no_spec_provided
|
86
|
+
url = "mysql://user:secret@localhost/mydatabase"
|
87
|
+
ENV["DATABASE_URL"] = url
|
88
|
+
connection_spec = mock_connection_spec(spec_hash, "mysql_connection")
|
89
|
+
ActiveRecord::ConnectionAdapters::ConnectionHandler.any_instance.
|
90
|
+
expects(:establish_connection).with("ActiveRecord::Base", connection_spec)
|
91
|
+
ActiveRecord::Base.establish_connection
|
92
|
+
end
|
93
|
+
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: activerecord_url_connections
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.3
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Glenn Gillen
|
@@ -10,10 +10,20 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-06-
|
13
|
+
date: 2011-06-28 00:00:00 +01:00
|
14
14
|
default_executable:
|
15
|
-
dependencies:
|
16
|
-
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: activerecord
|
18
|
+
prerelease: false
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: "0"
|
25
|
+
type: :runtime
|
26
|
+
version_requirements: *id001
|
17
27
|
description: Allows database connections to be defined as URLS, then converted to hash for use in ActiveRecord
|
18
28
|
email:
|
19
29
|
- glenn@rubypond.com
|
@@ -27,9 +37,11 @@ files:
|
|
27
37
|
- .gitignore
|
28
38
|
- Gemfile
|
29
39
|
- Rakefile
|
40
|
+
- Readme.md
|
30
41
|
- activerecord_url_connections.gemspec
|
31
42
|
- lib/activerecord_url_connections.rb
|
32
43
|
- lib/activerecord_url_connections/version.rb
|
44
|
+
- test/connection_test.rb
|
33
45
|
has_rdoc: true
|
34
46
|
homepage: ""
|
35
47
|
licenses: []
|
@@ -44,18 +56,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
44
56
|
requirements:
|
45
57
|
- - ">="
|
46
58
|
- !ruby/object:Gem::Version
|
47
|
-
hash: -2816335097435414650
|
48
|
-
segments:
|
49
|
-
- 0
|
50
59
|
version: "0"
|
51
60
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
61
|
none: false
|
53
62
|
requirements:
|
54
63
|
- - ">="
|
55
64
|
- !ruby/object:Gem::Version
|
56
|
-
hash: -2816335097435414650
|
57
|
-
segments:
|
58
|
-
- 0
|
59
65
|
version: "0"
|
60
66
|
requirements: []
|
61
67
|
|
@@ -64,5 +70,5 @@ rubygems_version: 1.6.0
|
|
64
70
|
signing_key:
|
65
71
|
specification_version: 3
|
66
72
|
summary: Convert URLs into AR friendly hashes
|
67
|
-
test_files:
|
68
|
-
|
73
|
+
test_files:
|
74
|
+
- test/connection_test.rb
|