app_conf 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|