app_config 2.4.1 → 2.5.0
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.
- checksums.yaml +4 -4
- data/.travis.yml +7 -2
- data/Gemfile.lock +2 -0
- data/README.md +102 -21
- data/app_config.gemspec +1 -0
- data/lib/app_config.rb +2 -0
- data/lib/app_config/storage.rb +1 -0
- data/lib/app_config/storage/mysql.rb +100 -0
- data/lib/app_config/storage/sqlite.rb +30 -0
- data/lib/app_config/storage/yaml.rb +10 -6
- data/lib/app_config/version.rb +1 -1
- data/spec/app_config/storage/mysql_spec.rb +75 -0
- data/spec/app_config/storage/sqlite_spec.rb +44 -0
- data/spec/app_config/storage/yaml_spec.rb +11 -0
- data/spec/spec_helper.rb +75 -0
- metadata +45 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a48c0515f2ec849d64e47343c4df57df7de7e80a
|
4
|
+
data.tar.gz: b2151f2cd3beb98a8065376b1d791a3f0918a6c2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 79ff5cf7464a593064a60a8410a23047867c807f98f572f9f5baff66492a8a01af049c18791c4111a26f91b86b3726da9403ecfe9cbfe5d6622577290f555200
|
7
|
+
data.tar.gz: 735ee7a382344299dbe7f979f47050b5de6616f478dc9e66ea6aa9a3bbc1a058d46e99ddd71a45a3a7556b5ada8e03fecf92ec7c298a458e2ea3b257ae0fda1c
|
data/.travis.yml
CHANGED
@@ -3,12 +3,17 @@ rvm:
|
|
3
3
|
- 1.9.2
|
4
4
|
- 1.9.3
|
5
5
|
- 2.0.0
|
6
|
+
- 2.1.2
|
6
7
|
|
7
8
|
before_script:
|
8
9
|
# Setup test Postgres database.
|
9
10
|
- psql -c 'create database app_config_test;' -U postgres
|
10
|
-
- psql -d app_config_test -U postgres -c 'CREATE TABLE app_config (id bigserial primary key, admin_email character varying(255), api_name character varying(255), api_key character varying(255));'
|
11
|
-
- psql -d app_config_test -U postgres -c "INSERT INTO app_config (admin_email, api_name, api_key) VALUES ('admin@example.com', 'Supr Webz 2.0', 'SUPERAWESOMESERVICE')"
|
11
|
+
- psql -d app_config_test -U postgres -c 'CREATE TABLE app_config (id bigserial primary key, admin_email character varying(255), api_name character varying(255), api_key character varying(255), true_option boolean, false_option boolean);'
|
12
|
+
- psql -d app_config_test -U postgres -c "INSERT INTO app_config (admin_email, api_name, api_key, true_option, false_option) VALUES ('admin@example.com', 'Supr Webz 2.0', 'SUPERAWESOMESERVICE', true, false);"
|
13
|
+
# Setup test MySQL database.
|
14
|
+
- mysql -u root -e 'create database app_config_test;'
|
15
|
+
- mysql -u root -D app_config_test -e 'CREATE TABLE app_config (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, admin_email VARCHAR(255), api_key VARCHAR(255), true_option BOOLEAN, false_option BOOLEAN);'
|
16
|
+
- mysql -u root -D app_config_test -e "INSERT INTO app_config (admin_email, api_key, true_option, false_option) VALUES ('admin@example.com', 'SUPERAWESOMESERVICE', true, false);"
|
12
17
|
|
13
18
|
env:
|
14
19
|
# Ignore warnings when running specs.
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -22,7 +22,7 @@ end
|
|
22
22
|
AppConfig.admin_email # => 'admin@example.com'
|
23
23
|
```
|
24
24
|
|
25
|
-
AppConfig also supports many different 'storage
|
25
|
+
AppConfig also supports many different 'storage methods', such as YAML and MongoDB,
|
26
26
|
allowing you to tailor AppConfig to many different use cases. For example,
|
27
27
|
storing your configuration in the same database as your development/production environment.
|
28
28
|
|
@@ -49,22 +49,6 @@ AppConfig.api_name # => 'Supr Webz 2.0'
|
|
49
49
|
AppConfig.api_key # => 'SUPERAWESOMESERVICE'
|
50
50
|
```
|
51
51
|
|
52
|
-
You can also use environments in the YAML file (like Rails `database.yml`):
|
53
|
-
|
54
|
-
```yaml
|
55
|
-
---
|
56
|
-
development:
|
57
|
-
api_url: 'http://localhost:3000/endpoint.json'
|
58
|
-
|
59
|
-
production:
|
60
|
-
api_url: 'http://api.example.com/endpoint.json'
|
61
|
-
```
|
62
|
-
|
63
|
-
```ruby
|
64
|
-
AppConfig.setup!(yaml: '/path/to/app_config.yml', env: :development)
|
65
|
-
AppConfig.api_url # => 'http://localhost:3000/endpoint.json'
|
66
|
-
```
|
67
|
-
|
68
52
|
|
69
53
|
## Mongo
|
70
54
|
|
@@ -72,6 +56,8 @@ You can pass a `:mongo` options hash to `AppConfig.setup!` which should contain
|
|
72
56
|
configuration values for a Mongo database. Check the `AppConfig::Storage::Mongo::DEFAULTS`
|
73
57
|
constant for the default Mongo connection options.
|
74
58
|
|
59
|
+
The '[mongo](https://rubygems.org/gems/mongo)' gem is required in order to use Mongo storage.
|
60
|
+
|
75
61
|
```ruby
|
76
62
|
# These are the defaults.
|
77
63
|
mongo_opts = {
|
@@ -105,6 +91,8 @@ Using PostgreSQL is similar to a Mongo setup.
|
|
105
91
|
The only current requirement is that the table have a primary key named `id`.
|
106
92
|
All other columns are used as configuration keys.
|
107
93
|
|
94
|
+
The '[pg](https://rubygems.org/gems/pg)' gem is required in order to use Postgres storage.
|
95
|
+
|
108
96
|
**Note:** The database and schema must exist prior to calling `AppConfig.setup!`.
|
109
97
|
|
110
98
|
Given this schema:
|
@@ -142,11 +130,75 @@ AppConfig.save!
|
|
142
130
|
```
|
143
131
|
|
144
132
|
|
133
|
+
## MySQL
|
134
|
+
|
135
|
+
Using MySQL is similar to Postgres, including the required primary key named `id`.
|
136
|
+
All other columns are used as configuration keys.
|
137
|
+
|
138
|
+
The '[mysql2](https://rubygems.org/gems/mysql2)' gem is required in order to use MySQL storage.
|
139
|
+
|
140
|
+
**Note:** The database and schema must exist prior to calling `AppConfig.setup!`.
|
141
|
+
|
142
|
+
Given this schema:
|
143
|
+
|
144
|
+
```sql
|
145
|
+
CREATE TABLE app_config (
|
146
|
+
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
147
|
+
admin_email VARCHAR(255) DEFAULT "admin@example.com",
|
148
|
+
api_key VARCHAR(255) DEFAULT "SOME_API_KEY",
|
149
|
+
true_option BOOLEAN DEFAULT true,
|
150
|
+
false_option BOOLEAN DEFAULT false
|
151
|
+
);
|
152
|
+
```
|
153
|
+
|
154
|
+
Setup AppConfig:
|
155
|
+
|
156
|
+
```ruby
|
157
|
+
# These are the defaults:
|
158
|
+
mysql_opts = {
|
159
|
+
host: 'localhost',
|
160
|
+
port: 3306,
|
161
|
+
database: 'app_config',
|
162
|
+
table: 'app_config',
|
163
|
+
username: nil,
|
164
|
+
password: nil,
|
165
|
+
}
|
166
|
+
|
167
|
+
AppConfig.setup!(mysql: mysql_opts)
|
168
|
+
|
169
|
+
AppConfig.admin_email # => 'admin@example.com'
|
170
|
+
|
171
|
+
# Update an existing value and save changes:
|
172
|
+
AppConfig.admin_email = 'another_admin@example.com'
|
173
|
+
AppConfig.save!
|
174
|
+
```
|
175
|
+
|
176
|
+
|
177
|
+
## SQLite
|
178
|
+
|
179
|
+
SQLite storage works the same as the other SQL storage methods, including the mandatory
|
180
|
+
primary key `id` column.
|
181
|
+
|
182
|
+
The '[sqlite3](https://rubygems.org/gems/sqlite3)' gem is required in order to use SQLite storage.
|
183
|
+
|
184
|
+
**Note:** The database schema must exist prior to calling `AppConfig.setup!`.
|
185
|
+
|
186
|
+
```ruby
|
187
|
+
# These are the defaults:
|
188
|
+
sqlite_opts = {
|
189
|
+
database: File.join(Dir.home, '.app_config.sqlite3'),
|
190
|
+
table: 'app_config',
|
191
|
+
}
|
192
|
+
|
193
|
+
AppConfig.setup!(sqlite: sqlite_opts)
|
194
|
+
```
|
195
|
+
|
196
|
+
|
145
197
|
## Using Storage Defaults
|
146
198
|
|
147
199
|
All storage options accept `true` as a value, which uses the default options for that storage.
|
148
200
|
|
149
|
-
For example, to use the [Mongo](
|
201
|
+
For example, to use the [Mongo](lib/app_config/storage/mongo.rb#L9) defaults:
|
150
202
|
|
151
203
|
```ruby
|
152
204
|
AppConfig.setup!(mongo: true)
|
@@ -154,9 +206,38 @@ AppConfig.setup!(mongo: true)
|
|
154
206
|
|
155
207
|
### Storage Defaults
|
156
208
|
|
157
|
-
* [Mongo](
|
158
|
-
* [
|
159
|
-
* [
|
209
|
+
* [Mongo](lib/app_config/storage/mongo.rb#L9)
|
210
|
+
* [MySQL](lib/app_config/storage/mysql.rb#L8)
|
211
|
+
* [Postgres](lib/app_config/storage/postgres.rb#L8)
|
212
|
+
* [SQLite](lib/app_config/storage/sqlite.rb#L9)
|
213
|
+
* [YAML](lib/app_config/storage/yaml.rb#L9)
|
214
|
+
|
215
|
+
|
216
|
+
### Environment Mode
|
217
|
+
|
218
|
+
The YAML storage method provides an `:env` option where you can organize the config like Rails `database.yml`:
|
219
|
+
|
220
|
+
```yaml
|
221
|
+
# Rails.root/config/app_config.yml
|
222
|
+
development:
|
223
|
+
title: 'Development Mode'
|
224
|
+
|
225
|
+
production:
|
226
|
+
title: 'Production Mode'
|
227
|
+
```
|
228
|
+
|
229
|
+
Pass a string or symbol to the `:env` option.
|
230
|
+
|
231
|
+
```ruby
|
232
|
+
# Rails.root/config/initializers/app_config.rb
|
233
|
+
AppConfig.setup!({
|
234
|
+
yaml: "#{Rails.root}/config/app_config.yml",
|
235
|
+
env: Rails.env
|
236
|
+
})
|
237
|
+
|
238
|
+
# Uses the given environment section of the config.
|
239
|
+
AppConfig.title # => 'Production Mode'
|
240
|
+
```
|
160
241
|
|
161
242
|
|
162
243
|
## Deprecation Note
|
data/app_config.gemspec
CHANGED
@@ -16,6 +16,7 @@ Gem::Specification.new do |s|
|
|
16
16
|
|
17
17
|
s.add_development_dependency 'bson_ext'
|
18
18
|
s.add_development_dependency 'mongo'
|
19
|
+
s.add_development_dependency 'mysql2'
|
19
20
|
s.add_development_dependency 'pg'
|
20
21
|
s.add_development_dependency 'rake'
|
21
22
|
s.add_development_dependency 'redcarpet'
|
data/lib/app_config.rb
CHANGED
@@ -23,6 +23,8 @@ module AppConfig
|
|
23
23
|
@@storage = AppConfig::Storage::YAML.new(@@options.delete(:yaml), @@options)
|
24
24
|
elsif @@options[:mongo]
|
25
25
|
@@storage = AppConfig::Storage::Mongo.new(@@options.delete(:mongo))
|
26
|
+
elsif @@options[:mysql]
|
27
|
+
@@storage = AppConfig::Storage::MySQL.new(@@options.delete(:mysql))
|
26
28
|
elsif @@options[:postgres]
|
27
29
|
@@storage = AppConfig::Storage::Postgres.new(@@options.delete(:postgres))
|
28
30
|
elsif @@options[:sqlite]
|
data/lib/app_config/storage.rb
CHANGED
@@ -3,6 +3,7 @@ module AppConfig
|
|
3
3
|
autoload :Base, 'app_config/storage/base'
|
4
4
|
autoload :ConfigData, 'app_config/storage/config_data'
|
5
5
|
autoload :Mongo, 'app_config/storage/mongo'
|
6
|
+
autoload :MySQL, 'app_config/storage/mysql'
|
6
7
|
autoload :Postgres, 'app_config/storage/postgres'
|
7
8
|
autoload :SQLite, 'app_config/storage/sqlite'
|
8
9
|
autoload :YAML, 'app_config/storage/yaml'
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module AppConfig
|
2
|
+
module Storage
|
3
|
+
|
4
|
+
require 'mysql2'
|
5
|
+
|
6
|
+
class MySQL < Storage::Base
|
7
|
+
|
8
|
+
DEFAULTS = {
|
9
|
+
host: 'localhost',
|
10
|
+
port: 3306,
|
11
|
+
database: 'app_config',
|
12
|
+
table: 'app_config',
|
13
|
+
username: nil,
|
14
|
+
password: nil,
|
15
|
+
}
|
16
|
+
|
17
|
+
def initialize(options)
|
18
|
+
# Allows passing `true` as an option, which uses the defaults.
|
19
|
+
if options.is_a?(Hash)
|
20
|
+
@options = DEFAULTS.merge(options)
|
21
|
+
else
|
22
|
+
@options = DEFAULTS
|
23
|
+
end
|
24
|
+
|
25
|
+
@table = @options.delete(:table)
|
26
|
+
|
27
|
+
setup_client!
|
28
|
+
fetch_data!
|
29
|
+
end
|
30
|
+
|
31
|
+
def reload!
|
32
|
+
fetch_data!
|
33
|
+
end
|
34
|
+
|
35
|
+
def save!
|
36
|
+
data_hash = @data.to_h
|
37
|
+
data_hash.delete(:id)
|
38
|
+
|
39
|
+
if @id
|
40
|
+
# Update existing row.
|
41
|
+
set_attrs = data_hash.map do |k, v|
|
42
|
+
if v.is_a?(TrueClass) || v.is_a?(FalseClass)
|
43
|
+
"#{k} = #{v}" # Don't quote booleans.
|
44
|
+
else
|
45
|
+
"#{k} = '#{v}'"
|
46
|
+
end
|
47
|
+
end.join(', ')
|
48
|
+
save_query = "UPDATE #{@table} SET #{set_attrs} WHERE id = #{@id};"
|
49
|
+
else
|
50
|
+
# Create a new row.
|
51
|
+
if data_hash.empty?
|
52
|
+
# Use defaults.
|
53
|
+
save_query = "INSERT INTO #{@table}(id) VALUES(NULL);"
|
54
|
+
else
|
55
|
+
columns = data_hash.keys.join(', ')
|
56
|
+
values = data_hash.map do |_, v|
|
57
|
+
if v.is_a?(TrueClass) || v.is_a?(FalseClass)
|
58
|
+
"#{v}" # Don't quote booleans.
|
59
|
+
else
|
60
|
+
"'#{v}'"
|
61
|
+
end
|
62
|
+
end.join(', ')
|
63
|
+
|
64
|
+
save_query = "INSERT INTO #{@table} (#{columns}) VALUES (#{values});"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
@client.query(save_query)
|
69
|
+
@client.affected_rows == 1
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def connected?
|
75
|
+
@client && @client.ping
|
76
|
+
end
|
77
|
+
|
78
|
+
def fetch_data!
|
79
|
+
raise 'Not connected to MySQL' unless connected?
|
80
|
+
|
81
|
+
fetch_query = "SELECT * FROM #{@table} ORDER BY id DESC LIMIT 1;"
|
82
|
+
|
83
|
+
result = @client.query(fetch_query, cast_booleans: true, symbolized_keys: true)
|
84
|
+
if result.size == 0
|
85
|
+
@data = Storage::ConfigData.new
|
86
|
+
else
|
87
|
+
result.each do |row|
|
88
|
+
@data = Storage::ConfigData.new(row)
|
89
|
+
@id = @data.id
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def setup_client!
|
95
|
+
@client = Mysql2::Client.new(@options)
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -25,6 +25,35 @@ module AppConfig
|
|
25
25
|
fetch_data!
|
26
26
|
end
|
27
27
|
|
28
|
+
def reload!
|
29
|
+
fetch_data!
|
30
|
+
end
|
31
|
+
|
32
|
+
def save!
|
33
|
+
data_hash = @data.to_h
|
34
|
+
data_hash.delete(:id)
|
35
|
+
|
36
|
+
if @id
|
37
|
+
# Update existing row.
|
38
|
+
set_attrs = data_hash.map { |k, v| "#{k} = '#{v}'" }.join(', ')
|
39
|
+
save_query = "UPDATE #{@table} SET #{set_attrs} WHERE id = #{@id};"
|
40
|
+
else
|
41
|
+
# Insert a new row.
|
42
|
+
if data_hash.empty?
|
43
|
+
# Use table defaults.
|
44
|
+
save_query = "INSERT INTO #{@table}(id) VALUES(NULL);"
|
45
|
+
else
|
46
|
+
columns = data_hash.keys.join(', ')
|
47
|
+
values = data_hash.map { |_, v| "'#{v}'" }.join(', ')
|
48
|
+
|
49
|
+
save_query = "INSERT INTO #{@table} (#{columns}) VALUES (#{values});"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
@database.execute(save_query)
|
54
|
+
@database.changes == 1
|
55
|
+
end
|
56
|
+
|
28
57
|
private
|
29
58
|
|
30
59
|
def fetch_data!
|
@@ -46,6 +75,7 @@ module AppConfig
|
|
46
75
|
end
|
47
76
|
|
48
77
|
@data = Storage::ConfigData.new(config)
|
78
|
+
@id = @data.id
|
49
79
|
end
|
50
80
|
|
51
81
|
end
|
@@ -13,15 +13,19 @@ module AppConfig
|
|
13
13
|
#
|
14
14
|
# Defaults to `Dir.home/.app_config.yml`
|
15
15
|
def initialize(path = DEFAULT_PATH, options = {})
|
16
|
-
#
|
17
|
-
path = DEFAULT_PATH
|
16
|
+
# Allow passing `true` as an option to use `DEFAULT_PATH`.
|
17
|
+
@path = path.is_a?(TrueClass) ? DEFAULT_PATH : path
|
18
|
+
@options = options
|
19
|
+
reload!
|
20
|
+
end
|
18
21
|
|
22
|
+
def reload!
|
19
23
|
# Make sure to use the top-level YAML module here.
|
20
|
-
if options.has_key?(:env)
|
21
|
-
env = options[:env].to_s # Force a String here since YAML's keys are strings.
|
22
|
-
@data = Storage::ConfigData.new(::YAML.load_file(path)[env])
|
24
|
+
if @options.has_key?(:env)
|
25
|
+
env = @options[:env].to_s # Force a String here since YAML's keys are strings.
|
26
|
+
@data = Storage::ConfigData.new(::YAML.load_file(@path)[env])
|
23
27
|
else
|
24
|
-
@data = Storage::ConfigData.new(::YAML.load_file(path))
|
28
|
+
@data = Storage::ConfigData.new(::YAML.load_file(@path))
|
25
29
|
end
|
26
30
|
end
|
27
31
|
|
data/lib/app_config/version.rb
CHANGED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AppConfig::Storage::MySQL do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
config_for_mysql(true)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should have some values' do
|
10
|
+
AppConfig.api_key.should_not be_nil
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should reload the data' do
|
14
|
+
# Set a value, but don't call AppConfig.save!
|
15
|
+
AppConfig.true_option = false
|
16
|
+
|
17
|
+
AppConfig.reload!
|
18
|
+
|
19
|
+
AppConfig.true_option.should == true
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should update the values' do
|
23
|
+
new_api_key = 'NEW_API_KEY'
|
24
|
+
new_admin_email = 'new_admin@example.com'
|
25
|
+
|
26
|
+
AppConfig.api_key = new_api_key
|
27
|
+
AppConfig.admin_email = new_admin_email
|
28
|
+
|
29
|
+
AppConfig.save!.should be_true
|
30
|
+
|
31
|
+
# Reload AppConfig
|
32
|
+
config_for_mysql
|
33
|
+
|
34
|
+
AppConfig.api_key.should == new_api_key
|
35
|
+
AppConfig.admin_email.should == new_admin_email
|
36
|
+
end
|
37
|
+
|
38
|
+
it "uses the defaults when 'true' is passed" do
|
39
|
+
AppConfig.reset!
|
40
|
+
|
41
|
+
# HACK: Use a test database as the 'default'.
|
42
|
+
old_dbname = AppConfig::Storage::MySQL::DEFAULTS[:database]
|
43
|
+
AppConfig::Storage::MySQL::DEFAULTS[:database] = 'app_config_test'
|
44
|
+
|
45
|
+
begin
|
46
|
+
AppConfig.setup!(mysql: true)
|
47
|
+
rescue Mysql2::Error => e
|
48
|
+
config_for_mysql
|
49
|
+
end
|
50
|
+
|
51
|
+
AppConfig.class_variable_get(:@@storage)
|
52
|
+
.instance_variable_get(:@options)
|
53
|
+
.should == AppConfig::Storage::MySQL::DEFAULTS
|
54
|
+
|
55
|
+
# HACK: Reset dbname default to original value.
|
56
|
+
AppConfig::Storage::MySQL::DEFAULTS[:database] = old_dbname
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should create a new row if @id is not set" do
|
60
|
+
# HACK: Save the old id so we can reset it.
|
61
|
+
original_id = AppConfig.class_variable_get(:@@storage)
|
62
|
+
.instance_variable_get(:@id)
|
63
|
+
|
64
|
+
AppConfig.class_variable_get(:@@storage)
|
65
|
+
.instance_variable_set(:@id, nil)
|
66
|
+
|
67
|
+
AppConfig.api_key = 'foobar'
|
68
|
+
AppConfig.save!.should be_true
|
69
|
+
|
70
|
+
# HACK: Reset the original id.
|
71
|
+
AppConfig.class_variable_get(:@@storage)
|
72
|
+
.instance_variable_set(:@id, original_id)
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -10,4 +10,48 @@ describe AppConfig::Storage::SQLite do
|
|
10
10
|
AppConfig.api_key.should_not be_nil
|
11
11
|
end
|
12
12
|
|
13
|
+
it 'should reload the data' do
|
14
|
+
# Save the old value, so we can make sure it hasn't changed.
|
15
|
+
admin_email = AppConfig.admin_email
|
16
|
+
|
17
|
+
# Set a value, but don't call AppConfig.save!
|
18
|
+
AppConfig.admin_email = 'CHANGED'
|
19
|
+
|
20
|
+
AppConfig.reload!
|
21
|
+
|
22
|
+
AppConfig.admin_email.should == admin_email
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should update the values' do
|
26
|
+
new_api_key = 'NEW_API_KEY'
|
27
|
+
new_admin_email = 'new_admin@example.com'
|
28
|
+
|
29
|
+
AppConfig.api_key = new_api_key
|
30
|
+
AppConfig.admin_email = new_admin_email
|
31
|
+
|
32
|
+
AppConfig.save!.should be_true
|
33
|
+
|
34
|
+
# Reload AppConfig (passing `false` to avoid wiping test db).
|
35
|
+
config_for_sqlite(false)
|
36
|
+
|
37
|
+
AppConfig.api_key.should == new_api_key
|
38
|
+
AppConfig.admin_email.should == new_admin_email
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should create a new row if @id is not set' do
|
42
|
+
# HACK: Save the old id so we can reset it.
|
43
|
+
original_id = AppConfig.class_variable_get(:@@storage)
|
44
|
+
.instance_variable_get(:@id)
|
45
|
+
|
46
|
+
AppConfig.class_variable_get(:@@storage)
|
47
|
+
.instance_variable_set(:@id, nil)
|
48
|
+
|
49
|
+
AppConfig.api_key = 'foobar'
|
50
|
+
AppConfig.save!.should be_true
|
51
|
+
|
52
|
+
# HACK: Reset the original id.
|
53
|
+
AppConfig.class_variable_get(:@@storage)
|
54
|
+
.instance_variable_set(:@id, original_id)
|
55
|
+
end
|
56
|
+
|
13
57
|
end
|
@@ -45,4 +45,15 @@ describe AppConfig::Storage::YAML do
|
|
45
45
|
AppConfig.production.should be_true
|
46
46
|
end
|
47
47
|
|
48
|
+
it 'should reload the data' do
|
49
|
+
config_for_yaml
|
50
|
+
original_api_key = AppConfig.api_key
|
51
|
+
|
52
|
+
# Set to some random value:
|
53
|
+
AppConfig.api_key = "foobar-#{rand(100)}"
|
54
|
+
|
55
|
+
AppConfig.reload!
|
56
|
+
AppConfig.api_key.should == original_api_key
|
57
|
+
end
|
58
|
+
|
48
59
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -30,6 +30,7 @@ RSpec.configure do |config|
|
|
30
30
|
mongo = AppConfig::Storage::Mongo::DEFAULTS.merge({
|
31
31
|
database: 'app_config_test',
|
32
32
|
})
|
33
|
+
|
33
34
|
begin
|
34
35
|
load_mongo_test_config(mongo) if load_test_data
|
35
36
|
config_for({mongo: mongo}.merge(opts))
|
@@ -44,6 +45,23 @@ RSpec.configure do |config|
|
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
48
|
+
def config_for_mysql(load_test_data = false, opts = {})
|
49
|
+
mysql = AppConfig::Storage::MySQL::DEFAULTS.merge({
|
50
|
+
database: 'app_config_test'
|
51
|
+
})
|
52
|
+
|
53
|
+
begin
|
54
|
+
load_mysql_test_config(mysql) if load_test_data
|
55
|
+
config_for({mysql: mysql}.merge(opts))
|
56
|
+
rescue Mysql2::Error => e
|
57
|
+
if e.to_s =~ /Can't connect/
|
58
|
+
pending "***** MySQL specs require a running MySQL server *****"
|
59
|
+
else
|
60
|
+
raise e
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
47
65
|
def config_for_postgres(load_test_data = false, opts = {})
|
48
66
|
postgres = AppConfig::Storage::Postgres::DEFAULTS.merge({
|
49
67
|
dbname: 'app_config_test'
|
@@ -115,6 +133,63 @@ RSpec.configure do |config|
|
|
115
133
|
end
|
116
134
|
end
|
117
135
|
|
136
|
+
def load_mysql_test_config(options)
|
137
|
+
original_options = options.dup
|
138
|
+
|
139
|
+
options.delete(:username) if options[:username].nil?
|
140
|
+
options.delete(:password) if options[:password].nil?
|
141
|
+
|
142
|
+
table = options.delete(:table)
|
143
|
+
|
144
|
+
begin
|
145
|
+
config = ::YAML.load_file(fixture('app_config.yml'))
|
146
|
+
attrs = config.map do |k, v|
|
147
|
+
if v.is_a?(String)
|
148
|
+
"#{k} VARCHAR(255)"
|
149
|
+
elsif v.is_a?(TrueClass) || v.is_a?(FalseClass)
|
150
|
+
"#{k} BOOLEAN"
|
151
|
+
end
|
152
|
+
end.join(', ')
|
153
|
+
|
154
|
+
values = config.values.map do |v|
|
155
|
+
if v.is_a?(TrueClass) || v.is_a?(FalseClass)
|
156
|
+
# Boolean types shouldn't be quoted.
|
157
|
+
"#{v}"
|
158
|
+
else
|
159
|
+
# But VARCHAR types should be.
|
160
|
+
"'#{v}'"
|
161
|
+
end
|
162
|
+
end.join(', ')
|
163
|
+
|
164
|
+
create_query = "CREATE TABLE #{table} (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, #{attrs});"
|
165
|
+
insert_query = "INSERT INTO #{table} (#{config.keys.join(', ')}) VALUES (#{values});"
|
166
|
+
|
167
|
+
client = Mysql2::Client.new(options)
|
168
|
+
client.query("USE #{options[:database]};")
|
169
|
+
|
170
|
+
begin
|
171
|
+
client.query(create_query)
|
172
|
+
rescue Mysql2::Error => e
|
173
|
+
case e.to_s
|
174
|
+
when /Table '#{table}' already exists/
|
175
|
+
# no-op
|
176
|
+
else
|
177
|
+
raise e
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
client.query(insert_query)
|
182
|
+
rescue Mysql2::Error => e
|
183
|
+
case e.to_s
|
184
|
+
when /Unknown database/
|
185
|
+
Mysql2::Client.new.query("CREATE DATABASE #{options[:database]};")
|
186
|
+
load_mysql_test_config(original_options)
|
187
|
+
else
|
188
|
+
raise e
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
118
193
|
def load_postgres_test_config(options)
|
119
194
|
original_options = options.dup
|
120
195
|
|
metadata
CHANGED
@@ -1,139 +1,153 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: app_config
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dale Campbell
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-05-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bson_ext
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: mongo
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: mysql2
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: pg
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
|
-
- -
|
59
|
+
- - ">="
|
46
60
|
- !ruby/object:Gem::Version
|
47
61
|
version: '0'
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
|
-
- -
|
66
|
+
- - ">="
|
53
67
|
- !ruby/object:Gem::Version
|
54
68
|
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: rake
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
|
-
- -
|
73
|
+
- - ">="
|
60
74
|
- !ruby/object:Gem::Version
|
61
75
|
version: '0'
|
62
76
|
type: :development
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
|
-
- -
|
80
|
+
- - ">="
|
67
81
|
- !ruby/object:Gem::Version
|
68
82
|
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: redcarpet
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
72
86
|
requirements:
|
73
|
-
- -
|
87
|
+
- - ">="
|
74
88
|
- !ruby/object:Gem::Version
|
75
89
|
version: '0'
|
76
90
|
type: :development
|
77
91
|
prerelease: false
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
79
93
|
requirements:
|
80
|
-
- -
|
94
|
+
- - ">="
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: '0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: rspec
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
86
100
|
requirements:
|
87
|
-
- -
|
101
|
+
- - ">="
|
88
102
|
- !ruby/object:Gem::Version
|
89
103
|
version: '0'
|
90
104
|
type: :development
|
91
105
|
prerelease: false
|
92
106
|
version_requirements: !ruby/object:Gem::Requirement
|
93
107
|
requirements:
|
94
|
-
- -
|
108
|
+
- - ">="
|
95
109
|
- !ruby/object:Gem::Version
|
96
110
|
version: '0'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: simplecov
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
|
-
- -
|
115
|
+
- - ">="
|
102
116
|
- !ruby/object:Gem::Version
|
103
117
|
version: '0'
|
104
118
|
type: :development
|
105
119
|
prerelease: false
|
106
120
|
version_requirements: !ruby/object:Gem::Requirement
|
107
121
|
requirements:
|
108
|
-
- -
|
122
|
+
- - ">="
|
109
123
|
- !ruby/object:Gem::Version
|
110
124
|
version: '0'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: sqlite3
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
114
128
|
requirements:
|
115
|
-
- -
|
129
|
+
- - ">="
|
116
130
|
- !ruby/object:Gem::Version
|
117
131
|
version: '0'
|
118
132
|
type: :development
|
119
133
|
prerelease: false
|
120
134
|
version_requirements: !ruby/object:Gem::Requirement
|
121
135
|
requirements:
|
122
|
-
- -
|
136
|
+
- - ">="
|
123
137
|
- !ruby/object:Gem::Version
|
124
138
|
version: '0'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
140
|
name: yard
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
128
142
|
requirements:
|
129
|
-
- -
|
143
|
+
- - ">="
|
130
144
|
- !ruby/object:Gem::Version
|
131
145
|
version: '0'
|
132
146
|
type: :development
|
133
147
|
prerelease: false
|
134
148
|
version_requirements: !ruby/object:Gem::Requirement
|
135
149
|
requirements:
|
136
|
-
- -
|
150
|
+
- - ">="
|
137
151
|
- !ruby/object:Gem::Version
|
138
152
|
version: '0'
|
139
153
|
description: An easy to use, framework agnostic, customizable library to easily store
|
@@ -144,9 +158,9 @@ executables: []
|
|
144
158
|
extensions: []
|
145
159
|
extra_rdoc_files: []
|
146
160
|
files:
|
147
|
-
- .gitignore
|
148
|
-
- .rspec
|
149
|
-
- .travis.yml
|
161
|
+
- ".gitignore"
|
162
|
+
- ".rspec"
|
163
|
+
- ".travis.yml"
|
150
164
|
- Gemfile
|
151
165
|
- Gemfile.lock
|
152
166
|
- README.md
|
@@ -159,12 +173,14 @@ files:
|
|
159
173
|
- lib/app_config/storage/base.rb
|
160
174
|
- lib/app_config/storage/config_data.rb
|
161
175
|
- lib/app_config/storage/mongo.rb
|
176
|
+
- lib/app_config/storage/mysql.rb
|
162
177
|
- lib/app_config/storage/postgres.rb
|
163
178
|
- lib/app_config/storage/sqlite.rb
|
164
179
|
- lib/app_config/storage/yaml.rb
|
165
180
|
- lib/app_config/version.rb
|
166
181
|
- spec/app_config/storage/config_data_spec.rb
|
167
182
|
- spec/app_config/storage/mongo_spec.rb
|
183
|
+
- spec/app_config/storage/mysql_spec.rb
|
168
184
|
- spec/app_config/storage/postgres_spec.rb
|
169
185
|
- spec/app_config/storage/sqlite_spec.rb
|
170
186
|
- spec/app_config/storage/yaml_spec.rb
|
@@ -179,35 +195,25 @@ licenses:
|
|
179
195
|
metadata: {}
|
180
196
|
post_install_message:
|
181
197
|
rdoc_options:
|
182
|
-
- --inline-source
|
183
|
-
- --charset=UTF-8
|
198
|
+
- "--inline-source"
|
199
|
+
- "--charset=UTF-8"
|
184
200
|
require_paths:
|
185
201
|
- lib
|
186
202
|
required_ruby_version: !ruby/object:Gem::Requirement
|
187
203
|
requirements:
|
188
|
-
- -
|
204
|
+
- - ">="
|
189
205
|
- !ruby/object:Gem::Version
|
190
206
|
version: '0'
|
191
207
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
192
208
|
requirements:
|
193
|
-
- -
|
209
|
+
- - ">="
|
194
210
|
- !ruby/object:Gem::Version
|
195
211
|
version: '0'
|
196
212
|
requirements: []
|
197
213
|
rubyforge_project:
|
198
|
-
rubygems_version: 2.0.
|
214
|
+
rubygems_version: 2.0.14
|
199
215
|
signing_key:
|
200
216
|
specification_version: 4
|
201
217
|
summary: Quick and easy application configuration.
|
202
|
-
test_files:
|
203
|
-
- spec/app_config/storage/config_data_spec.rb
|
204
|
-
- spec/app_config/storage/mongo_spec.rb
|
205
|
-
- spec/app_config/storage/postgres_spec.rb
|
206
|
-
- spec/app_config/storage/sqlite_spec.rb
|
207
|
-
- spec/app_config/storage/yaml_spec.rb
|
208
|
-
- spec/app_config/storage_spec.rb
|
209
|
-
- spec/app_config_spec.rb
|
210
|
-
- spec/fixtures/app_config.yml
|
211
|
-
- spec/fixtures/app_config_env.yml
|
212
|
-
- spec/spec_helper.rb
|
218
|
+
test_files: []
|
213
219
|
has_rdoc: true
|