configru 2.0.1 → 3.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.
data/ChangeLog.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Change Log
2
2
 
3
+ ## 3.0.0 (22 September 2012)
4
+
5
+ * Added option arrays
6
+ * Accessing a key that is not declared in `Configru.load` now raises
7
+ `NoMethodError`, rather than returning `nil`.
8
+
3
9
  ## 2.0.1 (14 September 2012)
4
10
 
5
11
  * Fix: Cascade options in loaded files
data/Gemfile CHANGED
@@ -2,7 +2,7 @@ source :rubygems
2
2
 
3
3
  group :development do
4
4
  gem "rake", "~> 0.9.0"
5
- gem "rspec", "~> 2.10.0"
5
+ gem "rspec", "~> 2.11.0"
6
6
  gem "simplecov", "~> 0.6.0"
7
7
  end
8
8
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- configru (2.0.1)
4
+ configru (3.0.0)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -9,14 +9,14 @@ GEM
9
9
  diff-lcs (1.1.3)
10
10
  multi_json (1.3.6)
11
11
  rake (0.9.2.2)
12
- rspec (2.10.0)
13
- rspec-core (~> 2.10.0)
14
- rspec-expectations (~> 2.10.0)
15
- rspec-mocks (~> 2.10.0)
16
- rspec-core (2.10.1)
17
- rspec-expectations (2.10.0)
12
+ rspec (2.11.0)
13
+ rspec-core (~> 2.11.0)
14
+ rspec-expectations (~> 2.11.0)
15
+ rspec-mocks (~> 2.11.0)
16
+ rspec-core (2.11.1)
17
+ rspec-expectations (2.11.3)
18
18
  diff-lcs (~> 1.1.3)
19
- rspec-mocks (2.10.1)
19
+ rspec-mocks (2.11.2)
20
20
  simplecov (0.6.4)
21
21
  multi_json (~> 1.0)
22
22
  simplecov-html (~> 0.5.3)
@@ -28,5 +28,5 @@ PLATFORMS
28
28
  DEPENDENCIES
29
29
  configru!
30
30
  rake (~> 0.9.0)
31
- rspec (~> 2.10.0)
31
+ rspec (~> 2.11.0)
32
32
  simplecov (~> 0.6.0)
data/lib/configru/dsl.rb CHANGED
@@ -10,8 +10,14 @@ module Configru
10
10
  instance_eval(&block)
11
11
  end
12
12
 
13
- def option(name, type = Object, default = nil, validate = nil, &block)
14
- option = Configru::Option.new(type, default, validate, nil)
13
+ def option(name, type = Object, default = nil, validation = nil, &block)
14
+ option = Configru::Option.new(type, default, validation, nil)
15
+ Option.new(option, &block) if block
16
+ @options[name.to_s] = option
17
+ end
18
+
19
+ def option_array(name, type = Object, default = [], validation = nil, &block)
20
+ option = Configru::OptionArray.new(type, default, validation, nil)
15
21
  Option.new(option, &block) if block
16
22
  @options[name.to_s] = option
17
23
  end
@@ -36,11 +42,11 @@ module Configru
36
42
  end
37
43
 
38
44
  def validate(v = nil, &block)
39
- @option.validate = v || block
45
+ @option.validation = v || block
40
46
  end
41
47
 
42
48
  def transform(&block)
43
- @option.transform = block
49
+ @option.transformation = block
44
50
  end
45
51
  end
46
52
  end
@@ -1,3 +1,38 @@
1
1
  module Configru
2
- Option = Struct.new(:type, :default, :validate, :transform)
2
+ class Option < Struct.new(:type, :default, :validation, :transformation)
3
+ def type?(value)
4
+ value.is_a?(self.type)
5
+ end
6
+
7
+ def valid?(value)
8
+ return true unless self.validation
9
+ self.validation === value
10
+ end
11
+
12
+ def transform(value)
13
+ return value unless self.transformation
14
+ self.transformation[value]
15
+ end
16
+ end
17
+
18
+ class OptionArray < Option
19
+ def type?(values)
20
+ return false unless values.is_a?(Array)
21
+ values.all? {|x| x.is_a?(self.type) }
22
+ end
23
+
24
+ def valid?(values)
25
+ return true unless self.validation
26
+ values.all? do |x|
27
+ # Use === instead of passing validation as the block to #all? so that
28
+ # non-block validations (Regexp, Range) work
29
+ self.validation === x
30
+ end
31
+ end
32
+
33
+ def transform(values)
34
+ return values unless self.transformation
35
+ values.map(&self.transformation)
36
+ end
37
+ end
3
38
  end
@@ -1,6 +1,8 @@
1
1
  module Configru
2
2
  class StructHash < Hash
3
- def method_missing(key)
3
+ def method_missing(key, *args)
4
+ # Raise NoMethodError if the key does not exist
5
+ super(key, *args) unless args.empty? && self.include?(key.to_s)
4
6
  self[key.to_s]
5
7
  end
6
8
  end
@@ -1,3 +1,3 @@
1
1
  module Configru
2
- VERSION = "2.0.1"
2
+ VERSION = "3.0.0"
3
3
  end
data/lib/configru.rb CHANGED
@@ -19,10 +19,10 @@ module Configru
19
19
 
20
20
  class OptionValidationError < OptionError
21
21
  def initialize(path, validation = nil)
22
- if validation
23
- super(path, "failed validation `#{validation.inspect}`")
24
- else
22
+ if validation.is_a?(Proc)
25
23
  super(path, "failed validation")
24
+ else
25
+ super(path, "failed validation `#{validation.inspect}`")
26
26
  end
27
27
  end
28
28
  end
@@ -80,21 +80,15 @@ module Configru
80
80
  value = option.default
81
81
  end
82
82
 
83
- unless value.is_a? option.type
83
+ unless option.type?(value)
84
84
  raise OptionTypeError.new(@option_path, option.type, value.class)
85
85
  end
86
86
 
87
- if option.validate.is_a? Proc
88
- unless option.validate[value]
89
- raise OptionValidationError.new(@option_path)
90
- end
91
- elsif option.validate
92
- unless option.validate === value
93
- raise OptionValidationError.new(@option_path, option.validate)
94
- end
87
+ unless option.valid?(value)
88
+ raise OptionValidationError.new(@option_path, option.validation)
95
89
  end
96
90
 
97
- output[key] = option.transform ? option.transform[value] : value
91
+ output[key] = option.transform(value)
98
92
 
99
93
  @option_path.pop
100
94
  end
@@ -105,9 +99,6 @@ module Configru
105
99
  end
106
100
 
107
101
  def self.method_missing(method, *args)
108
- # Let super raise the appropriate exception if it looks like the caller
109
- # wants a real method
110
- super(method, *args) unless args.empty?
111
- @root.send(method)
102
+ @root.send(method, *args)
112
103
  end
113
104
  end
@@ -11,12 +11,14 @@ describe Configru do
11
11
  Configru.example.should == 'example'
12
12
  end
13
13
 
14
- it 'behaves like a hash' do
14
+ it 'behaves like a StructHash' do
15
15
  Configru.load do
16
16
  option :example, String, 'example'
17
17
  end
18
18
 
19
19
  Configru['example'].should == 'example'
20
+ Configru.example.should == 'example'
21
+ expect { Configru.example2 }.to raise_error(NoMethodError)
20
22
  end
21
23
 
22
24
  it 'loads defaults if no files exist' do
@@ -123,4 +125,48 @@ describe Configru do
123
125
 
124
126
  Configru.example.should == 'example_dt'
125
127
  end
128
+
129
+ it 'checks that array option values are arrays' do
130
+ expect do
131
+ Configru.load(example_file :a) do
132
+ option_array :example
133
+ end
134
+ end.to raise_error(Configru::OptionTypeError)
135
+ end
136
+
137
+ it 'checks array option types' do
138
+ expect do
139
+ Configru.load(example_file :i) do
140
+ option_array :hetero, String
141
+ end
142
+ end.to raise_error(Configru::OptionTypeError)
143
+ end
144
+
145
+ it 'validates option arrays against values' do
146
+ expect do
147
+ Configru.load(example_file :i) do
148
+ option_array :example, Fixnum, [], 1..6
149
+ end
150
+ end.to raise_error(Configru::OptionValidationError)
151
+ end
152
+
153
+ it 'validates option arrays against blocks' do
154
+ expect do
155
+ Configru.load(example_file :i) do
156
+ option_array :example, Fixnum, [] do
157
+ validate {|x| x.even? }
158
+ end
159
+ end
160
+ end.to raise_error(Configru::OptionValidationError)
161
+ end
162
+
163
+ it 'applies transformations to option arrays' do
164
+ Configru.load(example_file :i) do
165
+ option_array :example, Fixnum, [] do
166
+ transform {|x| x + 1 }
167
+ end
168
+ end
169
+
170
+ Configru.example.should == [3, 5, 7, 8]
171
+ end
126
172
  end
data/spec/dsl_spec.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  describe Configru::DSL::Option do
2
2
  before do
3
- @option = Configru::Option.new(:type, :default, :validate, :transform)
3
+ @option = Configru::Option.new(:type, :default, :validation, :transformation)
4
4
  end
5
5
 
6
6
  it 'sets option type' do
@@ -24,7 +24,7 @@ describe Configru::DSL::Option do
24
24
  validate /example/
25
25
  end
26
26
 
27
- @option.validate.should == /example/
27
+ @option.validation.should == /example/
28
28
  end
29
29
 
30
30
  it 'sets option validate block' do
@@ -34,19 +34,19 @@ describe Configru::DSL::Option do
34
34
  end
35
35
  end
36
36
 
37
- @option.validate.should be_a(Proc)
38
- @option.validate.call.should == :example
37
+ @option.validation.should be_a(Proc)
38
+ @option.validation.call.should == :example
39
39
  end
40
40
 
41
- it 'sets option transofmr block' do
41
+ it 'sets option transform block' do
42
42
  described_class.new(@option) do
43
43
  transform do
44
44
  :example
45
45
  end
46
46
  end
47
47
 
48
- @option.transform.should be_a(Proc)
49
- @option.transform.call.should == :example
48
+ @option.transformation.should be_a(Proc)
49
+ @option.transformation.call.should == :example
50
50
  end
51
51
  end
52
52
 
@@ -58,6 +58,10 @@ describe Configru::DSL::OptionGroup do
58
58
 
59
59
  group.options.should have_key('example')
60
60
  group.options['example'].should be_a(Configru::Option)
61
+ group.options['example'].type.should == Object
62
+ group.options['example'].default.should be_nil
63
+ group.options['example'].validation.should be_nil
64
+ group.options['example'].transformation.should be_nil
61
65
  end
62
66
 
63
67
  it 'converts option names to strings' do
@@ -68,15 +72,25 @@ describe Configru::DSL::OptionGroup do
68
72
  group.options.should have_key('example')
69
73
  end
70
74
 
71
- it 'creates a default option' do
75
+ it 'creates an option array' do
72
76
  group = described_class.new do
73
- option 'example'
77
+ option_array 'example'
74
78
  end
75
79
 
80
+ group.options.should have_key('example')
81
+ group.options['example'].should be_a(Configru::OptionArray)
76
82
  group.options['example'].type.should == Object
77
- group.options['example'].default.should be_nil
78
- group.options['example'].validate.should be_nil
79
- group.options['example'].transform.should be_nil
83
+ group.options['example'].default.should == []
84
+ group.options['example'].validation.should be_nil
85
+ group.options['example'].transformation.should be_nil
86
+ end
87
+
88
+ it 'converts option array names to strings' do
89
+ group = described_class.new do
90
+ option_array :example
91
+ end
92
+
93
+ group.options.should have_key('example')
80
94
  end
81
95
 
82
96
  it 'runs the Option DSL' do
@@ -84,9 +98,13 @@ describe Configru::DSL::OptionGroup do
84
98
  option 'example' do
85
99
  type String
86
100
  end
101
+ option_array 'example_array' do
102
+ type String
103
+ end
87
104
  end
88
105
 
89
106
  group.options['example'].type.should == String
107
+ group.options['example_array'].type.should == String
90
108
  end
91
109
 
92
110
  it 'creates a group' do
@@ -0,0 +1,2 @@
1
+ hetero: ["string", 2]
2
+ example: [2, 4, 6, 7]
@@ -7,8 +7,13 @@ describe Configru::StructHash do
7
7
  @hash.should be_a_kind_of(Hash)
8
8
  end
9
9
 
10
- it 'returns nil for missing method key' do
11
- @hash.example.should be_nil
10
+ it 'raises NoMethodError for missing method key' do
11
+ expect { @hash.example }.to raise_error(NoMethodError)
12
+ end
13
+
14
+ it 'raises NoMethodError if method key exists but is called with arguments' do
15
+ @hash['example'] = :example
16
+ expect { @hash.example(:foo) }.to raise_error(NoMethodError)
12
17
  end
13
18
 
14
19
  it 'returns value for method key' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: configru
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 3.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-14 00:00:00.000000000 Z
12
+ date: 2012-09-22 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: YAML configuration file loader
15
15
  email:
@@ -42,6 +42,7 @@ files:
42
42
  - spec/example_files/example_f.yml
43
43
  - spec/example_files/example_g.yml
44
44
  - spec/example_files/example_h.yml
45
+ - spec/example_files/example_i.yml
45
46
  - spec/spec_helper.rb
46
47
  - spec/structhash_spec.rb
47
48
  homepage: https://github.com/programble/configru
@@ -58,7 +59,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
58
59
  version: '0'
59
60
  segments:
60
61
  - 0
61
- hash: 872203077689334122
62
+ hash: 2949675092247533978
62
63
  required_rubygems_version: !ruby/object:Gem::Requirement
63
64
  none: false
64
65
  requirements:
@@ -67,7 +68,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
67
68
  version: '0'
68
69
  segments:
69
70
  - 0
70
- hash: 872203077689334122
71
+ hash: 2949675092247533978
71
72
  requirements: []
72
73
  rubyforge_project:
73
74
  rubygems_version: 1.8.24
@@ -85,5 +86,6 @@ test_files:
85
86
  - spec/example_files/example_f.yml
86
87
  - spec/example_files/example_g.yml
87
88
  - spec/example_files/example_h.yml
89
+ - spec/example_files/example_i.yml
88
90
  - spec/spec_helper.rb
89
91
  - spec/structhash_spec.rb