confix 1.0.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.
@@ -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: