app_conf 0.3.0 → 0.4.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.
- data/README.markdown +29 -25
- data/Rakefile +1 -0
- data/app_conf.gemspec +1 -1
- data/lib/app_conf.rb +9 -25
- data/spec/app_conf_spec.rb +60 -55
- metadata +6 -5
data/README.markdown
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
AppConf
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
----------------------------------
|
|
3
|
+
YAML Backed Application Wide Configuration with a few extras ($config)
|
|
4
4
|
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Supports nested key/values
|
|
6
|
+
* Loading and Saving of YAML files
|
|
7
|
+
* Add further key/value pairs in code
|
|
7
8
|
* Use dot or bracket notation
|
|
8
|
-
*
|
|
9
|
+
* `$conf.to_hash` outputs a hash map of $conf key/values
|
|
10
|
+
* `$conf.from_hash` creates nested key/values from a hash
|
|
9
11
|
|
|
10
12
|
Installation
|
|
11
13
|
----------------------------------
|
|
@@ -30,58 +32,60 @@ other.yml
|
|
|
30
32
|
|
|
31
33
|
Code:
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
$conf = $conf.new
|
|
36
|
+
|
|
37
|
+
$conf.load('config.yml', 'other.yml')
|
|
38
|
+
$conf.fullname -> 'Joe Blogs'
|
|
39
|
+
$conf.user.name -> 'Joe'
|
|
40
|
+
$conf.user[:address]['street'] -> '1 Some Road'
|
|
37
41
|
|
|
38
42
|
Syntax
|
|
39
43
|
----------------------------------
|
|
40
44
|
|
|
41
45
|
Load multiple files at once:
|
|
42
46
|
|
|
43
|
-
|
|
47
|
+
$conf.load(*filenames)
|
|
44
48
|
|
|
45
49
|
Or individually:
|
|
46
50
|
|
|
47
|
-
|
|
48
|
-
|
|
51
|
+
$conf.load(filename1)
|
|
52
|
+
$conf.load(filename2)
|
|
49
53
|
|
|
50
54
|
Use either method calls or hash syntax:
|
|
51
55
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
56
|
+
$conf.fullname
|
|
57
|
+
$conf[:fullname]
|
|
58
|
+
$conf['fullname']
|
|
55
59
|
|
|
56
60
|
Infinitely nested keys:
|
|
57
61
|
|
|
58
|
-
|
|
62
|
+
$conf.multiple.nested.keys
|
|
59
63
|
|
|
60
64
|
Override existing values:
|
|
61
65
|
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
$conf.loaded.from.yaml = 'can override'
|
|
67
|
+
$conf['loaded']['from']['yaml'] = 'can override'
|
|
64
68
|
|
|
65
69
|
Set new values:
|
|
66
70
|
|
|
67
|
-
|
|
71
|
+
$conf.non_existing_value = 'can set'
|
|
68
72
|
|
|
69
73
|
Clear entire tree:
|
|
70
74
|
|
|
71
|
-
|
|
75
|
+
$conf.clear
|
|
72
76
|
|
|
73
77
|
Returns nil for non-existent keys:
|
|
74
78
|
|
|
75
|
-
|
|
76
|
-
|
|
79
|
+
$conf.non_existing -> nil
|
|
80
|
+
$conf.non_existing.name -> NoMethodError: undefined method 'name' for nil:NilClass
|
|
77
81
|
|
|
78
82
|
Use `from_hash` to create non-existent nodes:
|
|
79
83
|
|
|
80
|
-
|
|
84
|
+
$conf.from_hash({...})
|
|
81
85
|
|
|
82
86
|
Not dependent on Rails but easy to use with it. For example:
|
|
83
87
|
|
|
84
|
-
|
|
88
|
+
$conf.load('config.yml', "#{Rails.env}.yml")
|
|
85
89
|
|
|
86
90
|
Other stuff
|
|
87
91
|
----------------------------------
|
|
@@ -100,5 +104,5 @@ Known Issues
|
|
|
100
104
|
----------------------------------
|
|
101
105
|
Cannot assign values to unknown nested keys because they return nil (create the tree first):
|
|
102
106
|
|
|
103
|
-
|
|
107
|
+
$conf.from_hash({:non_existing => {:name => 'bla'}})
|
|
104
108
|
|
data/Rakefile
CHANGED
data/app_conf.gemspec
CHANGED
|
@@ -2,7 +2,7 @@ require 'base64'
|
|
|
2
2
|
|
|
3
3
|
Gem::Specification.new do |s|
|
|
4
4
|
s.name = 'app_conf'
|
|
5
|
-
s.version = '0.
|
|
5
|
+
s.version = '0.4.0'
|
|
6
6
|
s.authors = 'Phil Thompson'
|
|
7
7
|
s.email = Base64.decode64("cGhpbEBlbGVjdHJpY3Zpc2lvbnMuY29t\n")
|
|
8
8
|
s.summary = 'Simplest YAML Backed Application Wide Configuration (AppConfig)'
|
data/lib/app_conf.rb
CHANGED
|
@@ -4,16 +4,15 @@ class AppConf
|
|
|
4
4
|
def initialize
|
|
5
5
|
@hash = {}
|
|
6
6
|
end
|
|
7
|
-
@@root = new
|
|
8
7
|
|
|
9
|
-
def
|
|
8
|
+
def load(*filenames)
|
|
10
9
|
filenames.each do |filename|
|
|
11
10
|
content = YAML.load_file(filename)
|
|
12
11
|
from_hash(content) if content
|
|
13
12
|
end
|
|
14
13
|
end
|
|
15
14
|
|
|
16
|
-
def
|
|
15
|
+
def save(key, filename)
|
|
17
16
|
mode = File.exist?(filename) ? 'r+' : 'w+'
|
|
18
17
|
File.open(filename, mode) do |f|
|
|
19
18
|
unless f.eof?
|
|
@@ -23,25 +22,17 @@ class AppConf
|
|
|
23
22
|
end until line =~ /^---/ || f.eof?
|
|
24
23
|
line =~ /^---/ ? f.seek(pos) : f.rewind
|
|
25
24
|
end
|
|
26
|
-
hash = {key.to_s =>
|
|
25
|
+
hash = {key.to_s => self[key].to_hash}
|
|
27
26
|
YAML.dump(hash, f)
|
|
28
27
|
f.truncate(f.pos)
|
|
29
28
|
end
|
|
30
29
|
end
|
|
31
30
|
|
|
32
|
-
def
|
|
33
|
-
key ?
|
|
31
|
+
def clear key = nil
|
|
32
|
+
key ? @hash[key.to_s] = nil : @hash = {}
|
|
34
33
|
nil
|
|
35
34
|
end
|
|
36
35
|
|
|
37
|
-
def clear key
|
|
38
|
-
@hash[key.to_s] = nil
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def self.to_hash
|
|
42
|
-
@@root.to_hash
|
|
43
|
-
end
|
|
44
|
-
|
|
45
36
|
def to_hash
|
|
46
37
|
hash = {}
|
|
47
38
|
@hash.each {|k, v| hash[k] = v.is_a?(AppConf) ? v.to_hash : v }
|
|
@@ -69,19 +60,12 @@ class AppConf
|
|
|
69
60
|
end
|
|
70
61
|
end
|
|
71
62
|
|
|
72
|
-
def
|
|
73
|
-
@@root.send(method, *args)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def self.from_hash(hash, app_config = @@root)
|
|
63
|
+
def from_hash(hash)
|
|
77
64
|
hash.each do |key, value|
|
|
78
|
-
if value.is_a?(Hash)
|
|
79
|
-
|
|
80
|
-
value = from_hash(value, app_config[key] || new_app_config)
|
|
81
|
-
end
|
|
82
|
-
app_config[key] = value if new_app_config.nil? || value === new_app_config
|
|
65
|
+
value = (self[key] || AppConf.new).from_hash(value) if value.is_a?(Hash)
|
|
66
|
+
@hash[key.to_s] = value
|
|
83
67
|
end
|
|
84
|
-
|
|
68
|
+
self
|
|
85
69
|
end
|
|
86
70
|
end
|
|
87
71
|
|
data/spec/app_conf_spec.rb
CHANGED
|
@@ -4,10 +4,10 @@ require 'minitest/autorun'
|
|
|
4
4
|
require 'app_conf'
|
|
5
5
|
|
|
6
6
|
describe AppConf do
|
|
7
|
-
before
|
|
7
|
+
before do
|
|
8
8
|
FakeFS.activate!
|
|
9
9
|
|
|
10
|
-
config =
|
|
10
|
+
config =
|
|
11
11
|
"fullname: Joe Bloggs
|
|
12
12
|
user:
|
|
13
13
|
name:
|
|
@@ -20,157 +20,162 @@ user:
|
|
|
20
20
|
"
|
|
21
21
|
File.open('config.yml', 'w') {|f| f.write(config) }
|
|
22
22
|
File.open('other.yml', 'w') {|f| f.write(other)}
|
|
23
|
-
AppConf.
|
|
24
|
-
|
|
23
|
+
$conf = AppConf.new
|
|
24
|
+
$conf.load("config.yml")
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
after
|
|
27
|
+
after do
|
|
28
28
|
FakeFS.deactivate!
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
it 'returns nil on empty tree' do
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
$conf.clear
|
|
33
|
+
$conf.user.must_be_nil
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
it 'clears a key' do
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
$conf.user.clear :name
|
|
38
|
+
$conf.user.name.must_be_nil
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
it 'clears a key in root' do
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
$conf.clear :user
|
|
43
|
+
$conf.user.must_be_nil
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
it 'cleared key can be overwritten' do
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
$conf.clear :user
|
|
48
|
+
$conf.user = 'something'
|
|
49
|
+
$conf.user.must_equal 'something'
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'handles rake clobbering global' do
|
|
53
|
+
$conf.task = 'something'
|
|
54
|
+
$conf.task.must_equal 'something'
|
|
50
55
|
end
|
|
51
56
|
|
|
52
57
|
describe 'save' do
|
|
53
58
|
it 'saves a key and children to yml' do
|
|
54
|
-
|
|
59
|
+
$conf.save :user, 'temp.yml'
|
|
55
60
|
YAML.load_file('temp.yml').must_equal({'user' => {'name' => {'first' => 'Joe'}}})
|
|
56
61
|
end
|
|
57
62
|
|
|
58
63
|
it 'skips past comments' do
|
|
59
64
|
File.open('config.yml', 'w') {|f| f.write("# comment 1\n# comment 2\n\n--- \nRest of the config")}
|
|
60
|
-
|
|
65
|
+
$conf.save :user, 'config.yml'
|
|
61
66
|
File.read('config.yml').must_equal "# comment 1\n# comment 2\n\n--- \nuser: \n name: \n first: Joe\n"
|
|
62
67
|
end
|
|
63
68
|
|
|
64
69
|
it 'overwrites when no --- and single line' do
|
|
65
70
|
File.open('config.yml', 'w') {|f| f.write("some config\n") }
|
|
66
|
-
|
|
71
|
+
$conf.save :user, 'config.yml'
|
|
67
72
|
File.read('config.yml').must_equal "--- \nuser: \n name: \n first: Joe\n"
|
|
68
73
|
end
|
|
69
74
|
|
|
70
75
|
it 'overwrites when no --- and multiline' do
|
|
71
76
|
File.open('config.yml', 'w') {|f| f.write("# Some\n# comments\n\nconfig:\n name:\n") }
|
|
72
|
-
|
|
77
|
+
$conf.save :user, 'config.yml'
|
|
73
78
|
File.read('config.yml').must_equal "--- \nuser: \n name: \n first: Joe\n"
|
|
74
79
|
end
|
|
75
80
|
end
|
|
76
81
|
|
|
77
82
|
describe 'to_hash' do
|
|
78
83
|
it 'outputs a hash map' do
|
|
79
|
-
|
|
80
|
-
|
|
84
|
+
$conf.load("other.yml")
|
|
85
|
+
$conf.to_hash.must_equal({'fullname' => 'Joe Bloggs', 'user' => {'name' => {'first' => 'Joe'}, 'address' => {'street' => '1 Some Road'}}})
|
|
81
86
|
end
|
|
82
87
|
end
|
|
83
88
|
|
|
84
89
|
describe 'keys' do
|
|
85
90
|
it 'returns them' do
|
|
86
|
-
|
|
91
|
+
$conf.from_hash(:users => {:joe => nil, :mark => nil})
|
|
87
92
|
|
|
88
|
-
|
|
93
|
+
$conf.users.keys.must_equal %w(joe mark)
|
|
89
94
|
end
|
|
90
95
|
end
|
|
91
96
|
|
|
92
97
|
it 'creates from a hash' do
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
98
|
+
$conf.clear
|
|
99
|
+
$conf.from_hash(:user => {:name => {:first => 'Joe'}})
|
|
100
|
+
$conf.user.name.first.must_equal 'Joe'
|
|
96
101
|
end
|
|
97
102
|
|
|
98
103
|
it 'works with dot notation' do
|
|
99
|
-
|
|
104
|
+
$conf.fullname.must_equal 'Joe Bloggs'
|
|
100
105
|
end
|
|
101
106
|
|
|
102
107
|
it 'works with hash notation' do
|
|
103
|
-
|
|
104
|
-
|
|
108
|
+
$conf[:fullname].must_equal 'Joe Bloggs'
|
|
109
|
+
$conf['fullname'].must_equal 'Joe Bloggs'
|
|
105
110
|
end
|
|
106
111
|
|
|
107
112
|
describe 'clear' do
|
|
108
113
|
it 'clears all keys' do
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
114
|
+
$conf.fullname.wont_be_nil
|
|
115
|
+
$conf.clear
|
|
116
|
+
$conf.fullname.must_be_nil
|
|
112
117
|
end
|
|
113
118
|
|
|
114
|
-
it 'does not return
|
|
115
|
-
|
|
119
|
+
it 'does not return $conf instance' do
|
|
120
|
+
$conf.clear.must_be_nil
|
|
116
121
|
end
|
|
117
122
|
end
|
|
118
123
|
|
|
119
124
|
it 'works with nested dot notation' do
|
|
120
|
-
|
|
125
|
+
$conf.user.name.first.must_equal 'Joe'
|
|
121
126
|
end
|
|
122
127
|
|
|
123
128
|
it 'works with nested hash notation' do
|
|
124
|
-
|
|
125
|
-
|
|
129
|
+
$conf[:user][:name][:first].must_equal 'Joe'
|
|
130
|
+
$conf['user']['name']['first'].must_equal 'Joe'
|
|
126
131
|
end
|
|
127
132
|
|
|
128
133
|
it 'works with mixed notation' do
|
|
129
|
-
|
|
130
|
-
|
|
134
|
+
$conf[:user][:name][:first].must_equal 'Joe'
|
|
135
|
+
$conf.user['name'].first.must_equal 'Joe'
|
|
131
136
|
end
|
|
132
137
|
|
|
133
138
|
it 'works with multiple files' do
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
139
|
+
$conf.clear
|
|
140
|
+
$conf.load("config.yml", "other.yml")
|
|
141
|
+
$conf.user.address.street.must_equal '1 Some Road'
|
|
142
|
+
$conf.user.name.first.must_equal 'Joe'
|
|
138
143
|
end
|
|
139
144
|
|
|
140
145
|
it 'loads additional files' do
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
146
|
+
$conf.load("other.yml")
|
|
147
|
+
$conf.user.address.street.must_equal '1 Some Road'
|
|
148
|
+
$conf.user.name.first.must_equal 'Joe'
|
|
144
149
|
end
|
|
145
150
|
|
|
146
151
|
it 'handles empty files' do
|
|
147
152
|
File.open('empty.yml', 'w') {}
|
|
148
|
-
|
|
153
|
+
$conf.load('empty.yml')
|
|
149
154
|
end
|
|
150
155
|
|
|
151
156
|
it 'allows additional keys to be set' do
|
|
152
|
-
|
|
153
|
-
|
|
157
|
+
$conf.user.name.last = 'Bloggs'
|
|
158
|
+
$conf.user.name.last.must_equal 'Bloggs'
|
|
154
159
|
end
|
|
155
160
|
|
|
156
161
|
it 'allows additional keys to be set with hash notation' do
|
|
157
|
-
|
|
158
|
-
|
|
162
|
+
$conf.user[:name][:last] = 'Bloggs'
|
|
163
|
+
$conf.user.name.last.must_equal 'Bloggs'
|
|
159
164
|
end
|
|
160
165
|
|
|
161
166
|
it 'allows existing keys to be overridden' do
|
|
162
|
-
|
|
163
|
-
|
|
167
|
+
$conf.user.name.first = 'Jody'
|
|
168
|
+
$conf.user.name.first.must_equal 'Jody'
|
|
164
169
|
end
|
|
165
170
|
|
|
166
171
|
describe 'limitations' do
|
|
167
172
|
it 'returns nil when unknown key specified' do
|
|
168
|
-
|
|
173
|
+
$conf.unknown.must_be_nil
|
|
169
174
|
end
|
|
170
175
|
|
|
171
176
|
it 'does not allow nested items to be overwritten' do
|
|
172
|
-
lambda {
|
|
173
|
-
lambda {
|
|
177
|
+
lambda { $conf.user.name = 'something' }.must_raise RuntimeError
|
|
178
|
+
lambda { $conf[:user][:name] = 'something' }.must_raise RuntimeError
|
|
174
179
|
end
|
|
175
180
|
end
|
|
176
181
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: app_conf
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,11 +9,11 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date:
|
|
12
|
+
date: 2012-03-30 00:00:00.000000000Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: fakefs
|
|
16
|
-
requirement: &
|
|
16
|
+
requirement: &18793300 !ruby/object:Gem::Requirement
|
|
17
17
|
none: false
|
|
18
18
|
requirements:
|
|
19
19
|
- - ! '>='
|
|
@@ -21,7 +21,7 @@ dependencies:
|
|
|
21
21
|
version: '0'
|
|
22
22
|
type: :development
|
|
23
23
|
prerelease: false
|
|
24
|
-
version_requirements: *
|
|
24
|
+
version_requirements: *18793300
|
|
25
25
|
description:
|
|
26
26
|
email: phil@electricvisions.com
|
|
27
27
|
executables: []
|
|
@@ -55,9 +55,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
55
55
|
version: 1.3.6
|
|
56
56
|
requirements: []
|
|
57
57
|
rubyforge_project:
|
|
58
|
-
rubygems_version: 1.8.
|
|
58
|
+
rubygems_version: 1.8.10
|
|
59
59
|
signing_key:
|
|
60
60
|
specification_version: 3
|
|
61
61
|
summary: Simplest YAML Backed Application Wide Configuration (AppConfig)
|
|
62
62
|
test_files:
|
|
63
63
|
- spec/app_conf_spec.rb
|
|
64
|
+
has_rdoc:
|