confix 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a0772844b40f0090cc430fb8e72c68d3fad726df
4
+ data.tar.gz: e289f4ccd3908e8995210188391ed57ecf2d357e
5
+ SHA512:
6
+ metadata.gz: 3950a200697176564ae3757938e0c35a1b500910cdbcd9254b6aa1699a0a2fcb3abfa2e356eda5779cb6bbc1e9f22205e737466b01b322e0d14fae7215742c0d
7
+ data.tar.gz: 41d9129935d7a3140289f571e831e0e875b9655970a8c1dd0ebba3af2d5c9cb4c734aef0f11827d10adc2ff3dcad5a8de8cc384911688e8683f2654f397c8157
@@ -0,0 +1,29 @@
1
+ # See http://help.github.com/ignore-files/ for more about ignoring files.
2
+ #
3
+ # If you find yourself ignoring temporary files generated by your text editor
4
+ # or operating system, you probably want to add a global ignore instead:
5
+ # git config --global core.excludesfile ~/.gitignore_global
6
+
7
+ # Ignore .DS_Store
8
+ .DS_Store
9
+
10
+ # Ignore the output files.
11
+ /pkg
12
+
13
+ # Ignore bundler and database config and precompiled assets
14
+ /.bundle
15
+ /.env
16
+
17
+ # Ignore all logfiles and tempfiles.
18
+ /tmp
19
+
20
+ # Ignore TextMate projects
21
+ *.tmproj
22
+ *.sublime-project
23
+ *.sublime-workspace
24
+
25
+ # Documentation files and other stuff
26
+ .yardoc
27
+ /doc
28
+ /nbproject
29
+ /coverage
@@ -0,0 +1 @@
1
+ flux
@@ -0,0 +1 @@
1
+ ruby-2.0.0-p247
@@ -0,0 +1,6 @@
1
+ script: bundle exec rake
2
+ rvm:
3
+ - 2.0.0
4
+ branches:
5
+ only:
6
+ - master
@@ -0,0 +1,3 @@
1
+ ## 1.0.0
2
+
3
+ * Initial version
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in confix.gemspec
4
+ gemspec
@@ -0,0 +1,27 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ confix (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.2.4)
10
+ rake (10.1.0)
11
+ rspec (2.14.1)
12
+ rspec-core (~> 2.14.0)
13
+ rspec-expectations (~> 2.14.0)
14
+ rspec-mocks (~> 2.14.0)
15
+ rspec-core (2.14.5)
16
+ rspec-expectations (2.14.2)
17
+ diff-lcs (>= 1.1.3, < 2.0)
18
+ rspec-mocks (2.14.3)
19
+
20
+ PLATFORMS
21
+ ruby
22
+
23
+ DEPENDENCIES
24
+ bundler (~> 1.3)
25
+ confix!
26
+ rake
27
+ rspec (~> 2.14)
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Joost Lubach
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,56 @@
1
+ # Confix
2
+
3
+ Adds well-defined configuration options to any class. This gem is similar to Mark Bates' Configuratron, except that it takes a well-defined configuration structure as a basis. By providing inline documentation, the settings can easily be documented, allowing for better to understand configuration.
4
+
5
+ Confix adds support for loading configuration from a Hash (or YAML file), and provides templating to DRY up the configuration structure.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'confix'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install confix
20
+
21
+ ## Usage
22
+
23
+ Include this module in a new object, like so:
24
+
25
+ class MyConfiguration
26
+ include Confix
27
+
28
+ setting :database_url
29
+
30
+ config :external_api do
31
+ setting :enabled, false
32
+ setting :client_id
33
+ setting :client_secret
34
+ end
35
+ end
36
+
37
+ Now, one can access these properties like this:
38
+
39
+ cfg = MyConfiguration.new
40
+
41
+ cfg.database_url = 'http://www.database.com'
42
+ cfg.external_api.client_id = 'MyApp'
43
+
44
+ or
45
+
46
+ cfg.external_api.update :client_id => 'MyApp', :client_secret => '1234567890'
47
+
48
+ Method `setting` allows you to define a single setting, and method `config` allows you to define a sub-configuration.
49
+
50
+ ## Contributing
51
+
52
+ 1. Fork it
53
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
54
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
55
+ 4. Push to the branch (`git push origin my-new-feature`)
56
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'confix/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "confix"
8
+ spec.version = Confix::VERSION
9
+ spec.authors = ["Joost Lubach"]
10
+ spec.email = ["joost@yoazt.com"]
11
+ spec.description = %q[ Easy-to-use configuration using a well-defined structure. ]
12
+ spec.summary = %q[ Easy-to-use configuration using a well-defined structure. ]
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^spec/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec", "~> 2.14"
24
+ end
@@ -0,0 +1,412 @@
1
+ # This module makes it easy for any configuration object to define itself declaratively.
2
+ #
3
+ # === Usage
4
+ #
5
+ # Include this module in a new object, like this:
6
+ #
7
+ # class MyConfiguration
8
+ # include Confix
9
+ #
10
+ # setting :database_url
11
+ # config :external_api do
12
+ # setting :client_id
13
+ # setting :client_secret
14
+ # end
15
+ #
16
+ # end
17
+ #
18
+ # Now, one can access these properties like this:
19
+ #
20
+ # cfg = MyConfiguration.new
21
+ #
22
+ # cfg.database_url = 'http://www.database.com'
23
+ # cfg.external_api.client_id = 'MyApp'
24
+ #
25
+ # or
26
+ #
27
+ # cfg.external_api.update :client_id => 'MyApp', :client_secret => '1234567890'
28
+ #
29
+ # One can access the settings using indexers or method calls, just like in OpenStruct. Also,
30
+ # symbols or strings can be used by the indexers, mimicking HashWithIndifferentAccess. One
31
+ # can even get or set a property of a child configuration easily:
32
+ #
33
+ # raise 'invalid secret' if cfg['external_api.client_secret'] != secret
34
+ #
35
+ # === Notes
36
+ #
37
+ # Internally, all settings are stored in the 'root' configuration object. Imagine you have the
38
+ # following configuration setup:
39
+ #
40
+ # class Configuration
41
+ # include Confix
42
+ #
43
+ # config :child1 do
44
+ # setting :one
45
+ # end
46
+ # config :child2 do
47
+ # setting :two
48
+ # config :child2a do setting :three end
49
+ # end
50
+ # end
51
+ #
52
+ # Configurations +child1+ and +child2+ will not store their own configuration values. Instead,
53
+ # all configuration options are stored in the root object, using the following keys:
54
+ # * +child1.one+
55
+ # * +child2.two+
56
+ # * +child2.child2a.three
57
+ #
58
+ # This allows for rapid lookup and exporting. Any operation on a child configuration will forward
59
+ # their call to the root object.
60
+ #
61
+ # Convenience accessors are created to retrieve values. Using the example above, one can access
62
+ # the same setting in the following ways:
63
+ #
64
+ # config = Configuration.new
65
+ #
66
+ # config.child1.one = 'One'
67
+ # config.child2[:two] = 'Two'
68
+ # config['child2.child2a.three'] = 'Three'
69
+ #
70
+ # config[:child1].one # => 'One'
71
+ # config.child2[:one] # raises {UndefinedSetting}
72
+ # config.child2.child2a.three # => 'Three'
73
+ #
74
+ # If you use an intermediate key, you will get a Config object.
75
+ #
76
+ # config.child2 # #<Confix::Config @parent=#<Configuration>>
77
+ # config.child2 = 'something' # (raises {CannotModifyConfiguration})
78
+ #
79
+ # == Assigns
80
+ #
81
+ # You may add assignment variables to the {#assigns} hash. This hash is used to interpolate
82
+ # string settings.
83
+ #
84
+ # === Example
85
+ #
86
+ # config.assigns[:some_path] = '/path/to/something'
87
+ # config.path_setting = '%{some_path}/file.yml'
88
+ # config.path_setting # => '/path/to/something/file.yml'
89
+ module Confix
90
+
91
+ def self.included(base)
92
+ base.send :include, InstanceMethods
93
+ base.send :extend, ClassMethods
94
+
95
+ base.send :include, RootInstanceMethods
96
+ base.send :extend, RootClassMethods
97
+ end
98
+
99
+ # This exception is raised when an undefined setting was being accessed.
100
+ class UndefinedSetting < RuntimeError; end
101
+ class CannotModifyConfiguration < RuntimeError; end
102
+
103
+ ######
104
+ # Root instance methods
105
+
106
+ module RootInstanceMethods
107
+
108
+ # @!attribute [r] assigns
109
+ # @return [Hash]
110
+ # Assignment variables. These are available as interpolation arguments in any string
111
+ # setting. You can modify this hash.
112
+ def assigns
113
+ @assigns ||= {}
114
+ end
115
+
116
+ # Determines whether this configuration is a child configuration.
117
+ def child?
118
+ false
119
+ end
120
+
121
+ def fetch(name, default)
122
+ value = values[name]
123
+ value = default if value.nil?
124
+ value = value % assigns if value.is_a?(String)
125
+ value
126
+ end
127
+
128
+ # Gets the config root (this object).
129
+ def config_root
130
+ self
131
+ end
132
+
133
+ # Gets all configuration values.
134
+ def values
135
+ @values ||= {}
136
+ end
137
+
138
+ # Gets a hash containing intermediate configuration objects.
139
+ def configs
140
+ @configs ||= {}
141
+ end
142
+
143
+ end
144
+
145
+ ######
146
+ # Root class methods
147
+
148
+ module RootClassMethods
149
+
150
+ # Defines a reusable configuration template. If you specify a configuration you may refer to this template
151
+ # rather than specifying a block.
152
+ def template(name, &block)
153
+ raise ArgumentError, "block required" unless block
154
+ templates[name.to_s] = block
155
+ end
156
+
157
+ def templates
158
+ @templates ||= {}
159
+ end
160
+
161
+ end
162
+
163
+ module InstanceMethods
164
+
165
+ def self.included(target)
166
+ # Delegate common hash functions to the hash.
167
+ [ :each, :map, :select, :except, :symbolize_keys ].each do |method|
168
+ target.class_eval <<-RUBY, __FILE__, __LINE__+1
169
+ def #{method}(*args, &block)
170
+ to_hash.#{method} *args, &block
171
+ end
172
+ RUBY
173
+ end
174
+ end
175
+
176
+ ######
177
+ # Indexers
178
+
179
+ # Gets a setting by the given key.
180
+ #
181
+ # If the key refers to a child configuration, it retrieves an intermediate object
182
+ # that can be used for easy acess. See the examples in {Confix}.
183
+ #
184
+ # If the key refers to an existing setting, its value is returned. If the value
185
+ # was not found or was nil, the given default value is returned.
186
+ #
187
+ # If the value was not found, and no default was specified here, a default value
188
+ # for the setting is tried.
189
+ def get(key, default = nil)
190
+ key = key.to_s
191
+
192
+ default = self.class.defaults[key] if default.nil?
193
+
194
+ if self.class.configs[key]
195
+ # If the key refers to a child configuration class, instantiate this.
196
+ config_root.configs[self.class.expand_key(key)] ||= self.class.configs[key].new(self)
197
+ elsif child?
198
+ raise UndefinedSetting, "setting '#{self.class.expand_key(key)}' does not exist" unless self.class.key_defined?(key)
199
+
200
+ # Ask the config_root object for the value.
201
+ config_root.fetch(self.class.expand_key(key), default)
202
+ else
203
+ raise UndefinedSetting, "setting '#{self.class.expand_key(key)}' does not exist" unless self.class.key_defined?(key)
204
+
205
+ fetch(key, default)
206
+ end
207
+ end
208
+
209
+ # Sets a setting by the given key.
210
+ #
211
+ # If the key refers to a child configuration, an exception is returned.
212
+ def set(key, *value)
213
+ if value.length == 0 && key.is_a?(Hash)
214
+ # Apply the hash to the settings.
215
+ key.each { |key, value| set key, value }
216
+ else
217
+ raise ArgumentError, 'too many arguments (1 or 2 expected)' if value.length > 1
218
+ value = value.first
219
+
220
+ key = key.to_s
221
+
222
+ if self.class.configs[key]
223
+ raise CannotModifyConfiguration, "you cannot update a child configuration with anything else than a hash" unless value.is_a?(Hash)
224
+
225
+ config = (config_root.configs[self.class.expand_key(key)] ||= self.class.configs[key].new(self))
226
+ config.update value
227
+ elsif child?
228
+ raise UndefinedSetting, "setting '#{self.class.expand_key(key)}' does not exist" unless self.class.key_defined?(key)
229
+ config_root.values[self.class.expand_key(key)] = value
230
+ else
231
+ raise UndefinedSetting, "setting '#{self.class.expand_key(key)}' does not exist" unless self.class.key_defined?(key)
232
+ values[key] = value
233
+ end
234
+ end
235
+ end
236
+
237
+ # Gets all current configuration values.
238
+ def to_hash
239
+ values = {}
240
+ self.class.settings.each do |key|
241
+ values[key] = get(key)
242
+ end
243
+ self.class.configs.each do |key, config|
244
+ values[key] = get(key).to_hash
245
+ end
246
+ values
247
+ end
248
+
249
+ # (Recursively) updates this configuration from a hash.
250
+ def update(hash)
251
+
252
+ if hash
253
+ hash.each do |key, value|
254
+ set key, value
255
+ end
256
+ end
257
+
258
+ self
259
+ end
260
+
261
+ alias :[] :get
262
+ alias :[]= :set
263
+
264
+ ######
265
+ # Method missing
266
+
267
+ private
268
+
269
+ def method_missing(method, *args, &block)
270
+ raise UndefinedSetting, "setting '#{self.class.expand_key(method)}' does not exist"
271
+ end
272
+
273
+ end
274
+
275
+ module ClassMethods
276
+
277
+ ######
278
+ # DSL
279
+
280
+ # Defines a setting for this configuration. If this configuration was defined as a child
281
+ # of some parent configuration, this parent configuration will also create a definition
282
+ # for this setting, but no accessor methods.
283
+ #
284
+ # @param [Object] default Specify a default value for the setting.
285
+ def setting(key, default = nil)
286
+ key = key.to_s
287
+ raise ArgumentError, "invalid key: #{key}" unless Confix.valid_key?(key)
288
+
289
+ settings << key
290
+ defaults[key] = default if default
291
+ define_accessor_methods key
292
+ end
293
+
294
+ # Defines a child configuration for this configuration.
295
+ def config(key, template = nil, &block)
296
+ key = key.to_s
297
+ raise ArgumentError, "invalid key: #{key}" unless Confix.valid_key?(key)
298
+
299
+ config = Class.new(Config)
300
+ config.instance_variable_set '@parent', self
301
+ config.instance_variable_set '@key_from_root', expand_key(key)
302
+
303
+ # If no template or block are specified, infer a default template from the name.
304
+ if !template && !block
305
+ template = key
306
+ raise ArgumentError, "no template or block specified, and no template :#{key} found" unless config_root.templates[template]
307
+ elsif template
308
+ template = template.to_s
309
+ raise ArgumentError, "template :#{key} not found" unless config_root.templates[template]
310
+ end
311
+
312
+ # If a template is specified, first apply its block.
313
+ config.class_eval &config_root.templates[template] if template
314
+
315
+ # Apply the block.
316
+ config.class_eval &block if block
317
+
318
+ # Wrap up.
319
+ define_accessor_methods key
320
+ configs[key] = config
321
+ config
322
+ end
323
+
324
+ ######
325
+ # Attributes
326
+
327
+ def settings
328
+ @settings ||= []
329
+ end
330
+ def defaults
331
+ @defaults ||= {}
332
+ end
333
+ def configs
334
+ @configs ||= {}
335
+ end
336
+
337
+ def config_root
338
+ @parent ? @parent.config_root : self
339
+ end
340
+
341
+ attr_reader :key_from_root
342
+
343
+ ######
344
+ # Support
345
+
346
+ def expand_key(key)
347
+ [ @key_from_root, key ].compact.join('.')
348
+ end
349
+
350
+ def key_defined?(key)
351
+ if key.is_a?(Array)
352
+ tail = key
353
+ else
354
+ tail = key.to_s.split('.')
355
+ end
356
+
357
+ head = tail.shift
358
+ if configs.keys.include?(head)
359
+ configs[head].key_defined?(tail)
360
+ elsif settings.include?(head) && tail.empty?
361
+ true
362
+ else
363
+ false
364
+ end
365
+ end
366
+
367
+ private
368
+
369
+ def define_accessor_methods(key)
370
+ class_eval <<-RUBY, __FILE__, __LINE__+1
371
+ def #{key}; get(:#{key}) end
372
+ def #{key}=(value) set(:#{key}, value) end
373
+ RUBY
374
+ end
375
+
376
+ end
377
+
378
+ ######
379
+ # Child Config object.
380
+
381
+ # A simple Config object, which is created if people access a intermediate
382
+ # setting.
383
+ class Config
384
+ def initialize(parent = nil)
385
+ @parent = parent
386
+ end
387
+
388
+ # Resolves the root configuration object.
389
+ def config_root
390
+ @config_root ||= @parent ? @parent.config_root : self
391
+ end
392
+ def child?
393
+ true
394
+ end
395
+
396
+ include Confix::InstanceMethods
397
+ extend Confix::ClassMethods
398
+
399
+ def self.name
400
+ "Confix::Config(#{key_from_root})"
401
+ end
402
+
403
+ def inspect
404
+ super.sub(/#<Class:0x[a-f0-9]+>/, "#<#{self.class.name}>")
405
+ end
406
+ end
407
+
408
+ def self.valid_key?(key)
409
+ key.to_s !~ /[^_a-zA_Z0-9]/
410
+ end
411
+
412
+ end
@@ -0,0 +1,3 @@
1
+ module Confix
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,199 @@
1
+ require 'spec_helper'
2
+ require 'confix'
3
+
4
+ # TODO: Spec fetch
5
+
6
+ describe Confix do
7
+
8
+ class TestConfig
9
+ include Confix
10
+
11
+ setting :one
12
+ config :two do
13
+ setting :three
14
+ config :four do
15
+ setting :five, 'five'
16
+ end
17
+ end
18
+
19
+ template :six do
20
+ setting :eight
21
+ end
22
+ config :six
23
+ config :seven, :six do
24
+ setting :nine
25
+ end
26
+
27
+ end
28
+
29
+ before { @config = TestConfig.new }
30
+ subject { @config }
31
+
32
+ specify { @config.class.settings.should == [ 'one' ] }
33
+ specify { @config.class.configs['two'].should < Confix::Config }
34
+ specify { @config.class.configs['two'].settings.should == [ 'three' ] }
35
+ specify { @config.class.configs['two'].configs['four'].should < Confix::Config }
36
+
37
+ context 'when setting a basic setting' do
38
+
39
+ it 'should be accessible by method' do
40
+ @config.one = 'Hello'
41
+ @config.one.should == 'Hello'
42
+ @config[:one].should == 'Hello'
43
+ @config['one'].should == 'Hello'
44
+ end
45
+
46
+ it 'should be accessible by symbol' do
47
+ @config[:one] = 'Hello'
48
+ @config.one.should == 'Hello'
49
+ @config[:one].should == 'Hello'
50
+ @config['one'].should == 'Hello'
51
+ end
52
+
53
+ it 'should be accessible by string' do
54
+ @config['one'] = 'Hello'
55
+ @config.one.should == 'Hello'
56
+ @config[:one].should == 'Hello'
57
+ @config['one'].should == 'Hello'
58
+ end
59
+
60
+ it 'should not accept an undefined setting' do
61
+ -> { @config['four'] = 'Test' }.should raise_error(Confix::UndefinedSetting)
62
+ end
63
+
64
+ end
65
+
66
+ context 'when accessing an intermediate config' do
67
+
68
+ it 'should return a Confix::Config object by method' do
69
+ @config.two.should be_a(Confix::Config)
70
+ end
71
+
72
+ it 'should all be the same' do
73
+ @config.two.should be(@config[:two])
74
+ @config.two.should be(@config['two'])
75
+ end
76
+
77
+ it 'should return a Confix::Config object within a child' do
78
+ @config.two.four.should be_a(Confix::Config)
79
+ end
80
+
81
+ it 'should raise CannotModifyConfiguration when trying to set it' do
82
+ -> { @config['two'] = 'Hallo' }.should raise_error(Confix::CannotModifyConfiguration)
83
+ end
84
+
85
+ end
86
+
87
+ context 'when accessing a setting in a child object' do
88
+
89
+ it 'should be accessible by method' do
90
+ @config.two.three = 'Hello'
91
+ @config.two.three.should == 'Hello'
92
+ @config[:two].three.should == 'Hello'
93
+ @config['two'].three.should == 'Hello'
94
+ end
95
+
96
+ it 'should be accessible by symbol' do
97
+ @config[:two].three = 'Hello'
98
+ @config.two.three.should == 'Hello'
99
+ @config[:two].three.should == 'Hello'
100
+ @config['two'].three.should == 'Hello'
101
+ end
102
+
103
+ it 'should be accessible by string' do
104
+ @config['two'].three = 'Hello'
105
+ @config.two.three.should == 'Hello'
106
+ @config[:two].three.should == 'Hello'
107
+ @config['two'].three.should == 'Hello'
108
+ end
109
+
110
+ end
111
+
112
+ context 'when using root indexers' do
113
+
114
+ it 'should access a root level setting' do
115
+ @config.one = 'Hello'
116
+ @config['one'].should == 'Hello'
117
+ end
118
+
119
+ it 'should access a level-1 setting' do
120
+ @config.two.three = 'Hello2'
121
+ @config['two.three'].should == 'Hello2'
122
+ end
123
+
124
+ it 'should access a level-2 setting' do
125
+ @config.two.four.five = 'Hello3'
126
+ @config['two.four.five'].should == 'Hello3'
127
+ end
128
+
129
+ it 'should not accept an undefined setting' do
130
+ -> { @config['two.five'] = 'Test' }.should raise_error(Confix::UndefinedSetting)
131
+ end
132
+
133
+ end
134
+
135
+ describe 'values method' do
136
+
137
+ before {
138
+ @config.one = 'One'
139
+ @config.two.three = 'Three'
140
+ @config.two.four.five = 'Five'
141
+ }
142
+
143
+ it "should report all values from the root" do
144
+ @config.values.should == { 'one' => 'One', 'two.three' => 'Three', 'two.four.five' => 'Five' }
145
+ end
146
+
147
+ end
148
+
149
+ describe 'defaults' do
150
+ specify { @config.two.four.five.should == 'five' }
151
+ end
152
+
153
+ describe 'to_hash method' do
154
+
155
+ before {
156
+ @config.one = 'One'
157
+ @config.two.three = 'Three'
158
+ @config.two.four.five = 'Five'
159
+ }
160
+
161
+ it "should create a hash recursively" do
162
+ @config.to_hash.should == {"one"=>"One", "two"=>{"three"=>"Three", "four"=>{"five"=>"Five"}}, "six"=>{"eight"=>nil}, "seven"=>{"eight"=>nil, "nine"=>nil}}
163
+ end
164
+ it "should create a hash recursively from any level" do
165
+ @config.two.to_hash.should == {"three"=>"Three", "four"=>{"five"=>"Five"}}
166
+ end
167
+
168
+ end
169
+
170
+ it "should allow setting a child configuration" do
171
+ @config.two.four = { :five => 'Five' }
172
+ @config.two = { :three => 'Three' }
173
+
174
+ @config.two.to_hash.should == {"three"=>"Three", "four"=>{"five"=>"Five"}}
175
+ end
176
+
177
+ describe 'assigns' do
178
+ it "should use the assigns hash for any string setting" do
179
+ @config.assigns[:my_var] = 'test'
180
+ @config.one = 'Setting %{my_var}'
181
+ @config.one.should == 'Setting test'
182
+ end
183
+ end
184
+
185
+ describe 'templates' do
186
+
187
+ it "should apply template :six to config :six as no block was given" do
188
+ @config.six.should respond_to(:eight)
189
+ end
190
+ it "should apply template :six to config :seven as it was explicitly mentioned" do
191
+ @config.seven.should respond_to(:eight)
192
+ end
193
+ it "should also apply the given block" do
194
+ @config.seven.should respond_to(:nine)
195
+ end
196
+
197
+ end
198
+
199
+ end
@@ -0,0 +1,19 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter "spec/"
4
+ end
5
+
6
+ require 'confix'
7
+ require 'rspec/autorun'
8
+
9
+ RSpec.configure do |config|
10
+
11
+ config.mock_with :rspec do |config|
12
+ config.syntax = [ :should, :expect ]
13
+ end
14
+
15
+ end
16
+
17
+ # Requires supporting ruby files with custom matchers and macros, etc,
18
+ # in spec/support/ and its subdirectories.
19
+ Dir[File.expand_path("../support/**/*.rb", __FILE__)].each {|f| require f}
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: confix
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Joost Lubach
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-12-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '2.14'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '2.14'
55
+ description: ' Easy-to-use configuration using a well-defined structure. '
56
+ email:
57
+ - joost@yoazt.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - .gitignore
63
+ - .ruby-gemset
64
+ - .ruby-version
65
+ - .travis.yml
66
+ - CHANGELOG.md
67
+ - Gemfile
68
+ - Gemfile.lock
69
+ - LICENSE.txt
70
+ - README.md
71
+ - Rakefile
72
+ - confix.gemspec
73
+ - lib/confix.rb
74
+ - lib/confix/version.rb
75
+ - spec/confix_spec.rb
76
+ - spec/spec_helper.rb
77
+ homepage: ''
78
+ licenses:
79
+ - MIT
80
+ metadata: {}
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubyforge_project:
97
+ rubygems_version: 2.1.4
98
+ signing_key:
99
+ specification_version: 4
100
+ summary: Easy-to-use configuration using a well-defined structure.
101
+ test_files:
102
+ - spec/confix_spec.rb
103
+ - spec/spec_helper.rb
104
+ has_rdoc: