configru 3.3.1 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c07fa85118f6ae2cdf6732f59c88c29c2cf3e04d
4
- data.tar.gz: 1567cac755d01f457703f8a4bc0a58eaef7e31a0
3
+ metadata.gz: 4fe2eb4ab4567132c798bceaa960d6952f24f64f
4
+ data.tar.gz: 610aab18e8619ece1f85c3c5a6e2b4119375e7b9
5
5
  SHA512:
6
- metadata.gz: 5ec8dc807cdfb82290da302f4fe6187af246e9c27317cd467ee69f9e4ce754544f1dd8ff37b4c604a1a74e5174f6cfbd8568e4adb584fb725eb0c93111e88cfc
7
- data.tar.gz: e2ab059aade8ae09bfa47002127b5875ab266f1b84ab29542da3f50aaa1e11a22b5813a69ae1a0f8073dd5744795e43397ea2fd93295859863f9d945716a4de0
6
+ metadata.gz: 1b5684f556040ba711ebeae9b71012cb775ebc62209b8e067de935e1146ea130b7841d755512686983171b8487b9e0bcf04c22c30a9d6dabe67a6de48f1844b1
7
+ data.tar.gz: 3927b8495c5402df1723a2ed18e96f23a74dafc587ee02c8253a247ee084a9834d60fae8c33632da984f60d58728885d9e18d7a06458fe4463bbcde4a827fa35
data/.travis.yml CHANGED
@@ -3,11 +3,12 @@ rvm:
3
3
  - 1.8.7
4
4
  - 1.9.2
5
5
  - 1.9.3
6
+ - 2.0.0
6
7
  - jruby-18mode
7
8
  - jruby-19mode
8
9
  - rbx-18mode
9
- #- rbx-19mode # SimpleCov breaks
10
+ - rbx-19mode
10
11
 
11
12
  notifications:
12
13
  webhooks:
13
- - http://rcmp.tenthbit.net/
14
+ - http://rcmp.pw/
data/ChangeLog.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Change Log
2
2
 
3
+ ## 3.4.0 (8 October 2013)
4
+
5
+ * Added `Configru::Config` class
6
+ * Re-evaluate DSL block on reload
7
+
3
8
  ## 3.3.1 (29 September 2013)
4
9
 
5
10
  * Added license to Gemspec
data/Gemfile CHANGED
@@ -1,9 +1,9 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  group :development do
4
- gem "rake", "~> 10.1.0"
5
- gem "rspec", "~> 2.14.0"
6
- gem "simplecov", "~> 0.7.0"
4
+ gem 'rake', '~> 10.1.0'
5
+ gem 'rspec', '~> 2.14.0'
6
+ gem 'coveralls', :require => false
7
7
  end
8
8
 
9
9
  gemspec
data/Gemfile.lock CHANGED
@@ -1,14 +1,23 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- configru (3.3.1)
4
+ configru (3.4.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
+ coveralls (0.7.0)
10
+ multi_json (~> 1.3)
11
+ rest-client
12
+ simplecov (>= 0.7)
13
+ term-ansicolor
14
+ thor
9
15
  diff-lcs (1.2.4)
10
- multi_json (1.3.6)
16
+ mime-types (1.25)
17
+ multi_json (1.8.1)
11
18
  rake (10.1.0)
19
+ rest-client (1.6.7)
20
+ mime-types (>= 1.16)
12
21
  rspec (2.14.1)
13
22
  rspec-core (~> 2.14.0)
14
23
  rspec-expectations (~> 2.14.0)
@@ -21,12 +30,16 @@ GEM
21
30
  multi_json (~> 1.0)
22
31
  simplecov-html (~> 0.7.1)
23
32
  simplecov-html (0.7.1)
33
+ term-ansicolor (1.2.2)
34
+ tins (~> 0.8)
35
+ thor (0.18.1)
36
+ tins (0.11.0)
24
37
 
25
38
  PLATFORMS
26
39
  ruby
27
40
 
28
41
  DEPENDENCIES
29
42
  configru!
43
+ coveralls
30
44
  rake (~> 10.1.0)
31
45
  rspec (~> 2.14.0)
32
- simplecov (~> 0.7.0)
data/README.md CHANGED
@@ -1,52 +1,225 @@
1
- # Configru [![Build Status](https://secure.travis-ci.org/programble/configru.png?branch=master)](http://travis-ci.org/programble/configru) [![Dependency Status](https://gemnasium.com/programble/configru.png?travis)](https://gemnasium.com/programble/configru)
1
+ # Configru [![Gem Version](https://badge.fury.io/rb/configru.png)](http://badge.fury.io/rb/configru) [![Build Status](https://secure.travis-ci.org/programble/configru.png?branch=master)](http://travis-ci.org/programble/configru) [![Coverage Status](https://coveralls.io/repos/programble/configru/badge.png)](https://coveralls.io/r/programble/configru)
2
2
 
3
3
  YAML configuration file loader
4
4
 
5
5
  ## Usage
6
6
 
7
+ Install the gem or add it to your `Gemfile`:
8
+
7
9
  ```ruby
8
- # Gemfile
9
- gem "configru", "~> 3.3.0"
10
+ gem 'configru', '~> 3.4.0'
10
11
  ```
11
- ### Example
12
+
13
+ Next, require it and load a configuration:
12
14
 
13
15
  ```ruby
14
16
  require 'configru'
15
17
 
16
- Configru.load('config.yml') do
17
- option :username, String, 'example_user'
18
- option_required :token, Fixnum
19
- option_group :connection do
20
- option :server, String, 'example.com'
21
- option :port, Fixnum, 42
18
+ config = Configru::Config.new('config.yml')
19
+ ```
20
+
21
+ This example loads `config.yml` if it exists. Or at least it would, if
22
+ we told Configru the configuration options we wanted to load.
23
+
24
+ ### Options
25
+
26
+ Configru provides a DSL for specifying the options that should be
27
+ loaded. The main method to specify configuration options is `option`.
28
+
29
+ ```ruby
30
+ config = Configru::Config.new('config.yml') do
31
+ option :username, String, 'example_user', /^[A-Za-z1-9_]+$/
32
+ end
33
+ ```
34
+
35
+ `option` takes 4 arguments: the configuration key, the type of value,
36
+ the default value, and an optional validation check.
37
+
38
+ The configuration option above can then be accessed in two ways:
39
+
40
+ ```ruby
41
+ config.username
42
+ config['username']
43
+ ```
44
+
45
+ If the value in `config.yml` is a `String`, a
46
+ `Configru::OptionTypeError` will be raised. If the value does not pass
47
+ the validation check, a `Configru::OptionValidationError` will be
48
+ raised.
49
+
50
+ ### Validation
51
+
52
+ Validations are checked against the value of the option using the `===`
53
+ operator. This allows validations to be Procs, Regexps and Ranges. If
54
+ the validation is an Array, the value is checked using `include?`.
55
+
56
+ `option` can also be passed a block which can be used to set the
57
+ validation for the option. This allows a more convenient way to write
58
+ Proc validations.
59
+
60
+ ```ruby
61
+ config = Configru::Config.new('config.yml') do
62
+ option :username, String, 'example_user' do
63
+ validate {|o| o.length < 255 }
22
64
  end
23
- option :path, String, Dir.home do
24
- transform {|x| File.expand_path(x) }
25
- validate {|x| File.directory?(x) }
65
+ end
66
+ ```
67
+
68
+ ### Transformation
69
+
70
+ Configru also allows options to be transformed (using a Proc) as they
71
+ are loaded.
72
+
73
+ ```ruby
74
+ config = Configru::Config.new('config.yml') do
75
+ option :username, String, 'example' do
76
+ transform {|o| o + '_user' }
26
77
  end
27
- option_array :channels, String, ['foo', 'bar']
28
- option_bool :force, false
29
78
  end
79
+ ```
80
+
81
+ In the above example, if the username set in `config.yml` is
82
+ "winnifred", it will be transformed using the Proc and `config.username`
83
+ will be `"winnifred_user"`.
84
+
85
+ ### Required options
86
+
87
+ For configuration options that have no default and must be set in the
88
+ loaded configuration file, there is `option_required`. It takes the same
89
+ arguments as `option`, except for a default value.
90
+
91
+ ```ruby
92
+ config = Configru::Config.new('config.yml') do
93
+ option_required :username, String
94
+ end
95
+ ```
96
+
97
+ If a required option is not set in the loaded file, a
98
+ `Configru::OptionRequiredError` will be raised.
99
+
100
+ ### Array options
101
+
102
+ For options whose value should be a list, there is `option_array`. It
103
+ takes the same arguments as `option`, except the default value is
104
+ optional and defaults to an empty array. It behaves in the same way as
105
+ `option` except each element of the array is checked against the type
106
+ and the validation, and each element is transformed using the
107
+ transformation Proc.
108
+
109
+ ```ruby
110
+ config = Configru::Config.new('config.yml') do
111
+ option_array :users, String, ['user1', 'user2']
112
+ end
113
+ ```
114
+
115
+ ### Boolean options
116
+
117
+ Since Ruby's `true` and `false` do not share a class such as `Boolean`,
118
+ Configru provides a convenience method for boolean options,
119
+ `option_bool`. It take only an option key and a default value as
120
+ arguments.
121
+
122
+ ```ruby
123
+ config = Configru::Config.new('config.yml') do
124
+ option_bool :debug, false
125
+ end
126
+ ```
127
+
128
+ The above example is equivalent to the following:
129
+
130
+ ```ruby
131
+ config = Configru::Config.new('config.yml') do
132
+ option :debug, Object, false, [true, false]
133
+ end
134
+ ```
135
+
136
+ (This works because Array validations are checked using `include?`)
137
+
138
+ ### Option groups
30
139
 
31
- example = Example.new(Configru.connection.server, Configru.connection.port)
32
- example.login(Configru.username, Configru.token)
33
- Configru.channels.each do |x|
34
- example.sync(x, Configru.path, :force => Configru.force)
140
+ Configru allows nesting options in groups.
141
+
142
+ ```ruby
143
+ config = Configru::Config.new('config.yml') do
144
+ option_group :user do
145
+ option_required :name, String
146
+ option_required :password, String
147
+ end
35
148
  end
36
149
  ```
37
150
 
38
- These defaults are equivalent to the following YAML:
151
+ The format for the configuration file would be:
39
152
 
40
153
  ```yaml
41
- username: example_user
42
- connection:
43
- server: example.com
44
- port: 42
45
- path: ~
46
- channels:
47
- - foo
48
- - bar
49
- force: false
154
+ user:
155
+ name: example
156
+ password: example
157
+ ```
158
+
159
+ The above options can then be accessed using either method described
160
+ above:
161
+
162
+ ```ruby
163
+ config.user.name
164
+ config.user.password
165
+ config['user']['name']
166
+ config['user']['password']
167
+ ```
168
+
169
+ Option groups can, of course, be nested in other option groups.
170
+
171
+ ### Loading multiple files
172
+
173
+ Multiple files can be passed to `Configru::Config.new` and each will be
174
+ loaded sequentially, replacing any values from previous files with new
175
+ ones. This allows for loading a global configuration file and a user
176
+ configuration file that can override the global configuration.
177
+
178
+ ```ruby
179
+ config = Configru::Config.new('/etc/config.yml', File.expand_path('~/config.yml')) do
180
+ option :username, String, 'example_user'
181
+ end
182
+ ```
183
+
184
+ ### Reloading
185
+
186
+ To reload configuration files, call the `reload` method on the
187
+ `Configru::Config` object. Note that the entire DSL block will be
188
+ re-evaluated.
189
+
190
+ ```ruby
191
+ config = Configru::Config.new('config.yml') do
192
+ option :username, String, 'example_user'
193
+ end
194
+
195
+ config.reload
196
+ ```
197
+
198
+ ### Global loading
199
+
200
+ Since it can be tedious to pass around the `config` object all over an
201
+ application in order to have access to the configuration, the `Configru`
202
+ module itself can be used a `Configru::Config` object with the `load`
203
+ method.
204
+
205
+ ```ruby
206
+ Configru.load('config.yml') do
207
+ option :username, String, 'example_user'
208
+ end
209
+ ```
210
+
211
+ Option values can then be accessed on the `Configru` module in the same
212
+ way as on a `Configru::Config` object:
213
+
214
+ ```ruby
215
+ Configru.username
216
+ Configru['username']
217
+ ```
218
+
219
+ The global configuration can also be reloaded in the same way:
220
+
221
+ ```ruby
222
+ Configru.reload
50
223
  ```
51
224
 
52
225
  # License
data/lib/configru.rb CHANGED
@@ -1,112 +1,11 @@
1
- require 'configru/dsl'
2
- require 'configru/option'
3
- require 'configru/structhash'
4
-
5
- require 'yaml'
1
+ require 'configru/config'
6
2
 
7
3
  module Configru
8
- class OptionError < RuntimeError
9
- def initialize(path, message)
10
- super("#{path.join('.')}: #{message}")
11
- end
12
- end
13
-
14
- class OptionRequiredError < OptionError
15
- def initialize(path)
16
- super(path, 'option required')
17
- end
18
- end
19
-
20
- class OptionTypeError < OptionError
21
- def initialize(path, expected, got)
22
- super(path, "expected #{expected}, got #{got}")
23
- end
24
- end
25
-
26
- class OptionValidationError < OptionError
27
- def initialize(path, validation = nil)
28
- if validation.is_a?(Proc)
29
- super(path, "failed validation")
30
- else
31
- super(path, "failed validation `#{validation.inspect}`")
32
- end
33
- end
34
- end
35
-
36
4
  def self.load(*files, &block)
37
- @files = files.flatten
38
- @options = DSL::OptionGroup.new(&block).options
39
- @root = StructHash.new
40
- self.reload
41
- end
42
-
43
- def self.reload
44
- loaded_files = []
45
- @files.each do |file|
46
- if File.file?(file) && !File.zero?(file)
47
- self.load_file(file)
48
- loaded_files << file
49
- end
50
- end
51
-
52
- # Load all defaults if no files were loaded
53
- # TODO: loaded_files as instance var?
54
- # TODO: Better way to load defaults?
55
- @option_path = []
56
- self.load_group(@options, @root, {}) if loaded_files.empty?
57
- end
58
-
59
- def self.load_file(file)
60
- @option_path = []
61
- self.load_group(@options, @root, YAML.load_file(file) || {})
62
- end
63
-
64
- def self.load_group(option_group, output, input)
65
- option_group.each do |key, option|
66
- @option_path << key
67
-
68
- # option is a group
69
- if option.is_a? Hash
70
- if input.has_key?(key) && !input[key].is_a?(Hash)
71
- raise OptionTypeError.new(@option_path, Hash, input[key].class)
72
- end
73
- group_output = output[key] || StructHash.new
74
- self.load_group(option, group_output, input[key] || {})
75
- output[key] = group_output
76
- @option_path.pop
77
- next
78
- end
79
-
80
- if input.include? key
81
- value = input[key]
82
- elsif output.include? key # option has already been set
83
- @option_path.pop
84
- next
85
- elsif option.is_a? RequiredOption
86
- raise OptionRequiredError.new(@option_path)
87
- else # option has not been set
88
- value = option.default
89
- end
90
-
91
- unless option.type?(value)
92
- raise OptionTypeError.new(@option_path, option.type, value.class)
93
- end
94
-
95
- unless option.valid?(value)
96
- raise OptionValidationError.new(@option_path, option.validation)
97
- end
98
-
99
- output[key] = option.transform(value)
100
-
101
- @option_path.pop
102
- end
103
- end
104
-
105
- def self.[](key)
106
- @root[key]
5
+ @config = Config.new(*files, &block)
107
6
  end
108
7
 
109
- def self.method_missing(method, *args)
110
- @root.send(method, *args)
8
+ def self.method_missing(*args, &block)
9
+ @config.send(*args, &block)
111
10
  end
112
11
  end
@@ -0,0 +1,78 @@
1
+ %w[dsl option structhash exceptions].map {|r| require("configru/#{r}") }
2
+
3
+ require 'yaml'
4
+
5
+ module Configru
6
+ class Config < StructHash
7
+ def initialize(*files, &block)
8
+ @files = files.flatten
9
+ @dsl_block = block
10
+ reload
11
+ end
12
+
13
+ def reload
14
+ @options = DSL::OptionGroup.new(&@dsl_block).options
15
+
16
+ loaded_files = Array.new
17
+ @files.each do |file|
18
+ if File.file?(file) && !File.zero?(file)
19
+ load_file(file)
20
+ loaded_files << file
21
+ end
22
+ end
23
+
24
+ # Load all defaults if no files were loaded
25
+ # TODO: Some way to not special case this
26
+ @option_path = Array.new
27
+ load_group(@options, self, {}) if loaded_files.empty?
28
+ end
29
+
30
+ private
31
+
32
+ def load_file(file)
33
+ @option_path = Array.new
34
+ load_group(@options, self, YAML.load_file(file) || {})
35
+ end
36
+
37
+ def load_group(option_group, output, input)
38
+ option_group.each do |key, option|
39
+ @option_path << key
40
+
41
+ # option is a group
42
+ if option.is_a? Hash
43
+ if input.has_key?(key) && !input[key].is_a?(Hash)
44
+ raise OptionTypeError.new(@option_path, Hash, input[key].class)
45
+ end
46
+ group_output = output[key] || StructHash.new
47
+ load_group(option, group_output, input[key] || {})
48
+ output[key] = group_output
49
+ @option_path.pop
50
+ next
51
+ end
52
+
53
+ if input.include? key
54
+ value = input[key]
55
+ elsif output.include? key # option has already been set
56
+ @option_path.pop
57
+ next
58
+ elsif option.is_a? RequiredOption
59
+ raise OptionRequiredError.new(@option_path)
60
+ else # option has not been set
61
+ value = option.default
62
+ end
63
+
64
+ unless option.type?(value)
65
+ raise OptionTypeError.new(@option_path, option.type, value.class)
66
+ end
67
+
68
+ unless option.valid?(value)
69
+ raise OptionValidationError.new(@option_path, option.validation)
70
+ end
71
+
72
+ output[key] = option.transform(value)
73
+
74
+ @option_path.pop
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,29 @@
1
+ module Configru
2
+ class OptionError < RuntimeError
3
+ def initialize(path, message)
4
+ super("#{path.join('.')}: #{message}")
5
+ end
6
+ end
7
+
8
+ class OptionRequiredError < OptionError
9
+ def initialize(path)
10
+ super(path, 'option required')
11
+ end
12
+ end
13
+
14
+ class OptionTypeError < OptionError
15
+ def initialize(path, expected, got)
16
+ super(path, "expected #{expected}, got #{got}")
17
+ end
18
+ end
19
+
20
+ class OptionValidationError < OptionError
21
+ def initialize(path, validation = nil)
22
+ if validation.is_a?(Proc)
23
+ super(path, "failed validation")
24
+ else
25
+ super(path, "failed validation `#{validation.inspect}`")
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,3 +1,3 @@
1
1
  module Configru
2
- VERSION = "3.3.1"
2
+ VERSION = "3.4.0"
3
3
  end
@@ -0,0 +1,202 @@
1
+ describe Configru::Config do
2
+ def example_file(x)
3
+ "spec/example_files/example_#{x}.yml"
4
+ end
5
+
6
+ it 'loads defaults if no files are given' do
7
+ c = described_class.new do
8
+ option :example, String, 'example'
9
+ end
10
+
11
+ c.example.should == 'example'
12
+ end
13
+
14
+ it 'is a StructHash' do
15
+ c = described_class.new do
16
+ option :example, String, 'example'
17
+ end
18
+
19
+ c.is_a? Configru::StructHash
20
+ end
21
+
22
+ it 'loads defaults if no files exist' do
23
+ c = described_class.new(example_file :z) do
24
+ option :example, String, 'example'
25
+ end
26
+
27
+ c.example.should == 'example'
28
+ end
29
+
30
+ it 'loads defaults if file is empty' do
31
+ c = described_class.new(example_file :e) do
32
+ option :example, String, 'example'
33
+ end
34
+
35
+ c.example.should == 'example'
36
+ end
37
+
38
+ it 'loads defaults if file contains only whitespace' do
39
+ c = described_class.new(example_file :f) do
40
+ option :example, String, 'example'
41
+ end
42
+
43
+ c.example.should == 'example'
44
+ end
45
+
46
+ it 'loads a file' do
47
+ c = described_class.new(example_file :a) do
48
+ option :example
49
+ end
50
+
51
+ c.example.should == 'example_a'
52
+ end
53
+
54
+ it 'loads files in order' do
55
+ c = described_class.new(example_file(:a), example_file(:b)) do
56
+ option :example
57
+ end
58
+
59
+ c.example.should == 'example_b'
60
+ end
61
+
62
+ it 'cascades loaded files' do
63
+ c = described_class.new(example_file(:g), example_file(:h)) do
64
+ option :option1
65
+ option :option2
66
+ end
67
+
68
+ c.option1.should == 'example_g'
69
+ c.option2.should == 'example_h'
70
+ end
71
+
72
+ it 'loads a file with a group' do
73
+ c = described_class.new(example_file :c) do
74
+ option_group :example_group do
75
+ option :example
76
+ end
77
+ end
78
+
79
+ c.example_group.example.should == 'example_c'
80
+ end
81
+
82
+ it 'checks that group values are Hashes' do
83
+ expect do
84
+ c = described_class.new(example_file :a) do
85
+ option_group :example do
86
+ end
87
+ end
88
+ end.to raise_error(Configru::OptionTypeError)
89
+ end
90
+
91
+ it 'checks option types' do
92
+ expect do
93
+ c = described_class.new(example_file :d) do
94
+ option :string, String, ''
95
+ end
96
+ end.to raise_error(Configru::OptionTypeError)
97
+ end
98
+
99
+ it 'validates options against values' do
100
+ expect do
101
+ c = described_class.new(example_file :d) do
102
+ option :example, String, 'test', /test/
103
+ end
104
+ end.to raise_error(Configru::OptionValidationError)
105
+ end
106
+
107
+ it 'validates options against blocks' do
108
+ expect do
109
+ c = described_class.new(example_file :d) do
110
+ option :example, String, '' do
111
+ validate { false }
112
+ end
113
+ end
114
+ end.to raise_error(Configru::OptionValidationError)
115
+ end
116
+
117
+ it 'validates options against arrays' do
118
+ c = described_class.new(example_file :d) do
119
+ option :example, String, '', ['example_d']
120
+ end
121
+
122
+ c.example.should == 'example_d'
123
+
124
+ expect do
125
+ c = described_class.new(example_file :d) do
126
+ option :example, String, '', ['foo', 'bar']
127
+ end
128
+ end.to raise_error(Configru::OptionValidationError)
129
+ end
130
+
131
+ it 'applies transformations to options' do
132
+ c = described_class.new(example_file :d) do
133
+ option :example, String, '' do
134
+ transform {|x| x + 't' }
135
+ end
136
+ end
137
+
138
+ c.example.should == 'example_dt'
139
+ end
140
+
141
+ it 'checks that array option values are arrays' do
142
+ expect do
143
+ c = described_class.new(example_file :a) do
144
+ option_array :example
145
+ end
146
+ end.to raise_error(Configru::OptionTypeError)
147
+ end
148
+
149
+ it 'checks array option types' do
150
+ expect do
151
+ c = described_class.new(example_file :i) do
152
+ option_array :hetero, String
153
+ end
154
+ end.to raise_error(Configru::OptionTypeError)
155
+ end
156
+
157
+ it 'validates option arrays against values' do
158
+ expect do
159
+ c = described_class.new(example_file :i) do
160
+ option_array :example, Fixnum, [], 1..6
161
+ end
162
+ end.to raise_error(Configru::OptionValidationError)
163
+ end
164
+
165
+ it 'validates option arrays against blocks' do
166
+ expect do
167
+ c = described_class.new(example_file :i) do
168
+ option_array :example, Fixnum, [] do
169
+ validate {|x| x.even? }
170
+ end
171
+ end
172
+ end.to raise_error(Configru::OptionValidationError)
173
+ end
174
+
175
+ it 'applies transformations to option arrays' do
176
+ c = described_class.new(example_file :i) do
177
+ option_array :example, Fixnum, [] do
178
+ transform {|x| x + 1 }
179
+ end
180
+ end
181
+
182
+ c.example.should == [3, 5, 7, 8]
183
+ end
184
+
185
+ it 'requires required options' do
186
+ expect do
187
+ c = described_class.new(example_file :a) do
188
+ option_required :required
189
+ end
190
+ end.to raise_error(Configru::OptionRequiredError)
191
+ end
192
+
193
+ it 'executes DSL block on every reload' do
194
+ foo = 0
195
+ c = described_class.new do
196
+ foo += 1
197
+ end
198
+ c.reload
199
+
200
+ foo.should == 2
201
+ end
202
+ end
@@ -1,194 +1,11 @@
1
1
  describe Configru do
2
- def example_file(x)
3
- "spec/example_files/example_#{x}.yml"
4
- end
5
-
6
- it 'loads defaults if no files are given' do
7
- Configru.load do
8
- option :example, String, 'example'
9
- end
10
-
11
- Configru.example.should == 'example'
12
- end
13
-
14
- it 'behaves like a StructHash' do
2
+ it 'behaves like Config' do
15
3
  Configru.load do
16
4
  option :example, String, 'example'
17
5
  end
18
6
 
19
7
  Configru['example'].should == 'example'
20
8
  Configru.example.should == 'example'
21
- expect { Configru.example2 }.to raise_error(NoMethodError)
22
- end
23
-
24
- it 'loads defaults if no files exist' do
25
- Configru.load(example_file :z) do
26
- option :example, String, 'example'
27
- end
28
-
29
- Configru.example.should == 'example'
30
- end
31
-
32
- it 'loads defaults if file is empty' do
33
- Configru.load(example_file :e) do
34
- option :example, String, 'example'
35
- end
36
-
37
- Configru.example.should == 'example'
38
- end
39
-
40
- it 'loads defaults if file contains only whitespace' do
41
- Configru.load(example_file :f) do
42
- option :example, String, 'example'
43
- end
44
-
45
- Configru.example.should == 'example'
46
- end
47
-
48
- it 'loads a file' do
49
- Configru.load(example_file :a) do
50
- option :example
51
- end
52
-
53
- Configru.example.should == 'example_a'
54
- end
55
-
56
- it 'loads files in order' do
57
- Configru.load(example_file(:a), example_file(:b)) do
58
- option :example
59
- end
60
-
61
- Configru.example.should == 'example_b'
62
- end
63
-
64
- it 'cascades loaded files' do
65
- Configru.load(example_file(:g), example_file(:h)) do
66
- option :option1
67
- option :option2
68
- end
69
-
70
- Configru.option1.should == 'example_g'
71
- Configru.option2.should == 'example_h'
72
- end
73
-
74
- it 'loads a file with a group' do
75
- Configru.load(example_file :c) do
76
- option_group :example_group do
77
- option :example
78
- end
79
- end
80
-
81
- Configru.example_group.example.should == 'example_c'
82
- end
83
-
84
- it 'checks that group values are Hashes' do
85
- expect do
86
- Configru.load(example_file :a) do
87
- option_group :example do
88
- end
89
- end
90
- end.to raise_error(Configru::OptionTypeError)
91
- end
92
-
93
- it 'checks option types' do
94
- expect do
95
- Configru.load(example_file :d) do
96
- option :string, String, ''
97
- end
98
- end.to raise_error(Configru::OptionTypeError)
99
- end
100
-
101
- it 'validates options against values' do
102
- expect do
103
- Configru.load(example_file :d) do
104
- option :example, String, 'test', /test/
105
- end
106
- end.to raise_error(Configru::OptionValidationError)
107
- end
108
-
109
- it 'validates options against blocks' do
110
- expect do
111
- Configru.load(example_file :d) do
112
- option :example, String, '' do
113
- validate { false }
114
- end
115
- end
116
- end.to raise_error(Configru::OptionValidationError)
117
- end
118
-
119
- it 'validates options against arrays' do
120
- Configru.load(example_file :d) do
121
- option :example, String, '', ['example_d']
122
- end
123
-
124
- Configru.example.should == 'example_d'
125
-
126
- expect do
127
- Configru.load(example_file :d) do
128
- option :example, String, '', ['foo', 'bar']
129
- end
130
- end.to raise_error(Configru::OptionValidationError)
131
- end
132
-
133
- it 'applies transformations to options' do
134
- Configru.load(example_file :d) do
135
- option :example, String, '' do
136
- transform {|x| x + 't' }
137
- end
138
- end
139
-
140
- Configru.example.should == 'example_dt'
141
- end
142
-
143
- it 'checks that array option values are arrays' do
144
- expect do
145
- Configru.load(example_file :a) do
146
- option_array :example
147
- end
148
- end.to raise_error(Configru::OptionTypeError)
149
- end
150
-
151
- it 'checks array option types' do
152
- expect do
153
- Configru.load(example_file :i) do
154
- option_array :hetero, String
155
- end
156
- end.to raise_error(Configru::OptionTypeError)
157
- end
158
-
159
- it 'validates option arrays against values' do
160
- expect do
161
- Configru.load(example_file :i) do
162
- option_array :example, Fixnum, [], 1..6
163
- end
164
- end.to raise_error(Configru::OptionValidationError)
165
- end
166
-
167
- it 'validates option arrays against blocks' do
168
- expect do
169
- Configru.load(example_file :i) do
170
- option_array :example, Fixnum, [] do
171
- validate {|x| x.even? }
172
- end
173
- end
174
- end.to raise_error(Configru::OptionValidationError)
175
- end
176
-
177
- it 'applies transformations to option arrays' do
178
- Configru.load(example_file :i) do
179
- option_array :example, Fixnum, [] do
180
- transform {|x| x + 1 }
181
- end
182
- end
183
-
184
- Configru.example.should == [3, 5, 7, 8]
185
- end
186
-
187
- it 'requires required options' do
188
- expect do
189
- Configru.load(example_file :a) do
190
- option_required :required
191
- end
192
- end.to raise_error(Configru::OptionRequiredError)
9
+ expect { Configru.idonotexist }.to raise_error(NoMethodError)
193
10
  end
194
11
  end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,11 @@
1
1
  require 'bundler/setup'
2
2
 
3
3
  require 'simplecov'
4
+ require 'coveralls'
5
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
6
+ SimpleCov::Formatter::HTMLFormatter,
7
+ Coveralls::SimpleCov::Formatter
8
+ ]
4
9
  SimpleCov.start do
5
10
  add_filter '/spec/'
6
11
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: configru
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.1
4
+ version: 3.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Curtis McEnroe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-30 00:00:00.000000000 Z
11
+ date: 2013-10-09 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: YAML configuration file loader
14
14
  email:
@@ -27,10 +27,13 @@ files:
27
27
  - Rakefile
28
28
  - configru.gemspec
29
29
  - lib/configru.rb
30
+ - lib/configru/config.rb
30
31
  - lib/configru/dsl.rb
32
+ - lib/configru/exceptions.rb
31
33
  - lib/configru/option.rb
32
34
  - lib/configru/structhash.rb
33
35
  - lib/configru/version.rb
36
+ - spec/config_spec.rb
34
37
  - spec/configru_spec.rb
35
38
  - spec/dsl_spec.rb
36
39
  - spec/example_files/example_a.yml