option_initializer 1.3.0 → 1.5.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/README.md CHANGED
@@ -15,12 +15,15 @@ require 'option_initializer'
15
15
 
16
16
  class Person
17
17
  include OptionInitializer
18
- option_initializer :id, :name, :greetings => :block, :birthday => 1..3
19
- option_validator do |k, v|
20
- case k
21
- when :name
22
- raise ArgumentError, "invalid name" if v.empty?
23
- end
18
+
19
+ option_initializer :id,
20
+ :name => String,
21
+ :greetings => :&,
22
+ :birthday => 1..3,
23
+ :sex => Set[:male, :female]
24
+
25
+ option_validator :name do |v|
26
+ raise ArgumentError, "invalid name" if v.empty?
24
27
  end
25
28
 
26
29
  def initialize opts
@@ -39,6 +42,7 @@ john = Person.
39
42
  birthday(1990, 1, 1).
40
43
  greetings { |name| "Hi, I'm #{name}!" }.
41
44
  id(1000).
45
+ sex(:male).
42
46
  new
43
47
 
44
48
  # becomes equivalent to
@@ -46,6 +50,7 @@ john = Person.new(
46
50
  :id => 1000,
47
51
  :name => 'John Doe',
48
52
  :birthday => [1990, 1, 1],
53
+ :sex => :male,
49
54
  :greetings => proc { |name| "Hi, I'm #{name}!" }
50
55
  )
51
56
 
@@ -62,3 +67,51 @@ Person.
62
67
  say_hello
63
68
  ```
64
69
 
70
+ ## Option definitions and validators
71
+
72
+ ```ruby
73
+ class MyClass
74
+ include OptionInitializer
75
+
76
+ option_initializer :a, # Single object of any type
77
+ :b => 2, # Two objects of any type
78
+ :c => 1..3, # 1, 2, or 3 objects of any type
79
+ :d => :*, # Any number of objects of any type
80
+ :e => :&, # Block
81
+ :f => Fixnum, # Single Fixnum object
82
+ :g => [Fixnum, String, Symbol], # Fixnum, String, and Symbol
83
+ :h => Set[true, false], # Value must be either true or false
84
+ :i => [Fixnum, Set[true, false]] # Fixnum and boolean
85
+
86
+ # Validator for :f
87
+ option_validator :f do |v|
88
+ raise ArgumentError if v < 0
89
+ end
90
+
91
+ # Generic validator
92
+ option_validator do |k, v|
93
+ case k
94
+ when :a
95
+ # ...
96
+ when :b
97
+ # ...
98
+ end
99
+ end
100
+
101
+ def initialize arg1, arg2, options
102
+ validate_options options
103
+ @options = options
104
+ end
105
+ end
106
+
107
+ object = MyClass.a(o).
108
+ b(o1, o2).
109
+ c(o1, o2, o3).
110
+ d(o1, o2).
111
+ e { |o| o ** o }.
112
+ f(f).
113
+ g(f, str, sym).
114
+ h(true).
115
+ i(100, false).
116
+ new(a1, a2)
117
+ ```
@@ -1,12 +1,11 @@
1
- require "option_initializer/version"
1
+ require 'option_initializer/version'
2
+ require 'set'
2
3
 
3
4
  module OptionInitializer
4
5
  class OptionInitializingTemplate
5
6
  attr_reader :options
6
7
  alias to_h options
7
8
 
8
- const_set :VALIDATORS, []
9
-
10
9
  def initialize base, options, need_validation
11
10
  validate options if need_validation
12
11
  @base = base
@@ -42,10 +41,13 @@ module OptionInitializer
42
41
  end
43
42
 
44
43
  def validate hash
45
- self.class.const_get(:VALIDATORS).each do |validator|
46
- hash.each do |k, v|
47
- validator.call k, v
48
- end
44
+ avals, vals = [:ARG_VALIDATORS, :VALIDATORS].map { |s|
45
+ self.class.const_get(s)
46
+ }
47
+ hash.each do |k, v|
48
+ avals[k] && avals[k].call(v)
49
+ vals[k] && vals[k].call(v)
50
+ vals[nil] && vals[nil].call(k, v)
49
51
  end
50
52
  end
51
53
  end
@@ -65,19 +67,25 @@ module OptionInitializer
65
67
  raise TypeError,
66
68
  "wrong argument type #{options.class} (expected Hash)" unless
67
69
  options.is_a?(Hash)
68
- return if options.respond_to?(:option_validated?)
69
- validators = self.class.const_get(:OptionInitializing).const_get(:VALIDATORS)
70
- validators.each do |validator|
71
- options.each do |k, v|
72
- validator.call k, v
73
- end
70
+ return if options.respond_to?(:option_validated?) && options.option_validated?
71
+ avals, vals = [:ARG_VALIDATORS, :VALIDATORS].map { |s|
72
+ self.class.const_get(:OptionInitializing).const_get(s)
73
+ }
74
+ options.each do |k, v|
75
+ avals[k] && avals[k].call(v)
76
+ vals[k] && vals[k].call(v)
77
+ vals[nil] && vals[nil].call(k, v)
74
78
  end
75
79
  options
76
80
  end
77
81
 
78
82
  def self.included base
79
83
  unless base.constants.map(&:to_sym).include?(:OptionInitializing)
80
- base.const_set :OptionInitializing, OptionInitializingTemplate.dup
84
+ base.const_set :OptionInitializing, oi = OptionInitializingTemplate.dup
85
+ oi.class_eval do
86
+ const_set :VALIDATORS, {}
87
+ const_set :ARG_VALIDATORS, {}
88
+ end
81
89
  end
82
90
 
83
91
  base.class_eval do
@@ -87,11 +95,12 @@ module OptionInitializer
87
95
  end
88
96
  end
89
97
 
90
- def base.option_validator &block
98
+ def base.option_validator sym = nil, &block
91
99
  raise ArgumentError, "block must be given" unless block
92
- raise ArgumentError, "invalid arity (expected: 2)" unless block.arity == 2
100
+ a = sym ? 1 : 2
101
+ raise ArgumentError, "invalid arity (expected: #{a})" unless block.arity == a
93
102
  oi = self.const_get(:OptionInitializing)
94
- oi.const_get(:VALIDATORS).push block
103
+ oi.const_get(:VALIDATORS)[sym] = block
95
104
  end
96
105
 
97
106
  def base.option_initializer *syms
@@ -103,16 +112,98 @@ module OptionInitializer
103
112
  arr << [sym.to_sym, 1]
104
113
  when Hash
105
114
  arr.concat sym.map { |k, v|
106
- unless (v.is_a?(Fixnum) && v > 0) || (v.is_a?(Range) && v.begin > 0) || v == :block
107
- raise ArgumentError, "invalid number of arguments specified for #{k}"
115
+ case v
116
+ when Fixnum
117
+ raise ArgumentError, "invalid number of arguments specified for #{k}" if v <= 0
118
+ when Range
119
+ raise ArgumentError, "invalid number of arguments specified for #{k}" if v.begin < 0
120
+ when Set
121
+ raise ArgumentError, "empty set of values specified for #{k}" if v.length == 0
122
+ when Array
123
+ raise ArgumentError, "invalid option definition: `#{v}'" unless v.all? { |e| e.is_a?(Class) || e.is_a?(Set) }
124
+ when Class, :*, :&
125
+ # noop
126
+ else
127
+ raise ArgumentError, "invalid option definition: `#{v}'"
108
128
  end
109
129
  [k.to_sym, v]
110
130
  }
111
131
  else
112
- raise ArgumentError, "invalid option specification"
132
+ raise ArgumentError, "invalid option definition"
113
133
  end
114
134
  }
115
135
 
136
+ # Setup validators
137
+ vals = oi.const_get(:ARG_VALIDATORS)
138
+ pairs.each do |pair|
139
+ sym, nargs = pair
140
+ case nargs
141
+ when :&
142
+ vals[sym] = proc { |v|
143
+ if !v.is_a?(Proc)
144
+ raise TypeError, "wrong argument type #{v.class} (expected Proc)"
145
+ end
146
+ }
147
+ when 1
148
+ # good to go
149
+ vals.delete sym
150
+ when :*
151
+ vals[sym] = proc { |v|
152
+ if !v.is_a?(Array)
153
+ raise ArgumentError, "wrong number of arguments (1 for #{nargs})"
154
+ end
155
+ }
156
+ when Fixnum
157
+ vals[sym] = proc { |v|
158
+ if !v.is_a?(Array)
159
+ raise ArgumentError, "wrong number of arguments (1 for #{nargs})"
160
+ elsif nargs != v.length
161
+ raise ArgumentError, "wrong number of arguments (#{v.length} for #{nargs})"
162
+ end
163
+ }
164
+ when Range
165
+ vals[sym] = proc { |v|
166
+ if !v.is_a?(Array)
167
+ raise ArgumentError, "wrong number of arguments (1 for #{nargs})"
168
+ elsif !nargs.include?(v.length)
169
+ raise ArgumentError, "wrong number of arguments (#{v.length} for #{nargs})"
170
+ end
171
+ }
172
+ when Set
173
+ vals[sym] = proc { |v|
174
+ if !nargs.include?(v)
175
+ raise ArgumentError, "invalid option value: `#{v}' (expected one of #{nargs.to_a.inspect})"
176
+ end
177
+ }
178
+ when Array
179
+ vals[sym] = proc { |v|
180
+ if !v.is_a?(Array)
181
+ raise ArgumentError, "wrong number of arguments (1 for #{nargs.length})"
182
+ elsif nargs.length != v.length
183
+ raise ArgumentError, "wrong number of arguments (#{v.length} for #{nargs.length})"
184
+ else
185
+ v.zip(nargs).each do |ec|
186
+ e, c = ec
187
+ case c
188
+ when Class
189
+ raise TypeError, "wrong argument type #{e.class} (expected #{c})" unless e.is_a?(c)
190
+ when Set
191
+ unless c.include?(e)
192
+ raise ArgumentError, "invalid option value: `#{e}' (expected one of #{c.to_a.inspect})"
193
+ end
194
+ end
195
+ end
196
+ end
197
+ }
198
+ when Class
199
+ vals[sym] = proc { |v|
200
+ if !v.is_a?(nargs)
201
+ raise TypeError, "wrong argument type #{v.class} (expected #{nargs})"
202
+ end
203
+ }
204
+ end
205
+ end
206
+
116
207
  # Class methods
117
208
  pairs.each do |pair|
118
209
  sym = pair.first
@@ -133,38 +224,25 @@ module OptionInitializer
133
224
  sym, nargs = pair
134
225
  undef_method(sym) if method_defined?(sym)
135
226
  define_method(sym) do |*v, &b|
136
- case nargs
137
- when :block
138
- if b
139
- if v.empty?
140
- merge(sym => b)
141
- else
142
- raise ArgumentError, "only block expected"
143
- end
144
- else
145
- raise ArgumentError, "block expected but not given"
146
- end
147
- when 1
148
- if b && v.empty?
227
+ if nargs == :&
228
+ if v.empty?
149
229
  merge(sym => b)
150
- elsif b && !v.empty?
151
- raise ArgumentError, "wrong number of arguments (#{v.length} for 0 when block given)"
152
- elsif v.length == 1
153
- merge(sym => v.first)
154
230
  else
155
- raise ArgumentError, "wrong number of arguments (#{v.length} for 1)"
231
+ raise ArgumentError, "wrong number of arguments (#{v.length} for 0)"
156
232
  end
157
- when Range, Fixnum
158
- if b
159
- raise ArgumentError, "block not expected"
160
- elsif (nargs.is_a?(Range) && !nargs.include?(v.length)) ||
161
- (nargs.is_a?(Fixnum) && nargs != v.length)
162
- raise ArgumentError, "wrong number of arguments (#{v.length} for #{nargs})"
233
+ elsif b
234
+ raise ArgumentError, "block not expected"
235
+ else
236
+ case nargs
237
+ when 1, Class, Set
238
+ if v.length == 1
239
+ merge(sym => v.first)
240
+ else
241
+ raise ArgumentError, "wrong number of arguments (#{v.length} for 1)"
242
+ end
163
243
  else
164
244
  merge(sym => v)
165
245
  end
166
- else
167
- raise ArgumentError, "invalid option specification"
168
246
  end
169
247
  end
170
248
  end
@@ -1,3 +1,3 @@
1
1
  module OptionInitializer
2
- VERSION = "1.3.0"
2
+ VERSION = "1.5.0"
3
3
  end
@@ -16,4 +16,6 @@ Gem::Specification.new do |gem|
16
16
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
17
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
18
  gem.require_paths = ["lib"]
19
+
20
+ gem.add_development_dependency 'simplecov'
19
21
  end
@@ -1,14 +1,17 @@
1
1
  $VERBOSE = true
2
2
 
3
3
  require 'rubygems'
4
+ require 'simplecov'
5
+ SimpleCov.start
4
6
  require 'minitest/autorun'
5
7
  require 'option_initializer'
8
+ require 'set'
6
9
 
7
10
  class MyClass
8
11
  include OptionInitializer
9
- option_initializer :aaa, :bbb
10
- option_initializer :ccc, :ddd
12
+ option_initializer :aaa, :bbb => 1
11
13
  option_initializer :ccc, :ddd
14
+ option_initializer :ccc, :ddd => :&
12
15
 
13
16
  attr_reader :a, :b, :options, :y
14
17
 
@@ -38,19 +41,23 @@ class MyClass2
38
41
  option_initializer! :aaa
39
42
  option_initializer :bbb, :ccc
40
43
  option_validator do |k, v|
41
- @@validate_count += 1
44
+ @@validate_count += 100
42
45
  case k
43
46
  when :aaa
44
- raise ArgumentError if v == 0
47
+ raise ArgumentError
45
48
  end
46
49
  end
47
50
  option_validator do |k, v|
48
51
  @@validate_count += 1
49
52
  case k
50
53
  when :aaa
51
- raise ArgumentError if v < 0
54
+ raise ArgumentError if v == 0
52
55
  end
53
56
  end
57
+ option_validator :aaa do |v|
58
+ @@validate_count += 1
59
+ raise ArgumentError if v < 0
60
+ end
54
61
 
55
62
  def initialize options
56
63
  validate_options options
@@ -79,14 +86,15 @@ class MyClass3
79
86
  end
80
87
  end
81
88
 
82
- class MyClass4
89
+ class MyClassVarArgs
83
90
  attr_reader :options
84
91
 
85
92
  include OptionInitializer
86
93
  option_initializer :two => 2,
87
94
  :two_or_three => 2..3,
88
95
  :yet_two_or_three => 2...4,
89
- :b => :block
96
+ :b => :&,
97
+ :v => :*
90
98
 
91
99
  def initialize options
92
100
  validate_options @options = options
@@ -97,15 +105,36 @@ class MyClass5
97
105
  include OptionInitializer
98
106
  end
99
107
 
108
+ class MyClassWithTypes
109
+ include OptionInitializer
110
+ option_initializer :a => Fixnum,
111
+ :b => String,
112
+ :c => Numeric,
113
+ :d => Array,
114
+ :e => [Fixnum, String, Array],
115
+ :f => Set[true, false],
116
+ :g => [ Set[true, false], Set[1, 2, 3] ]
117
+
118
+ attr_reader :options
119
+ def initialize options
120
+ validate_options options
121
+ @options = options
122
+ end
123
+ end
124
+
100
125
  # Excerpt from README
101
126
  class Person
102
127
  include OptionInitializer
103
- option_initializer! :id, :name, :greetings, :birthday => 1..3
104
- option_validator do |k, v|
105
- case k
106
- when :name
107
- raise ArgumentError, "invalid name" if v.empty?
108
- end
128
+
129
+ option_initializer :id,
130
+ :name => String,
131
+ :greetings => :&,
132
+ :birthday => 1..3,
133
+ :sex => Set[:male, :female]
134
+ option_initializer!
135
+
136
+ option_validator :name do |v|
137
+ raise ArgumentError, "invalid name" if v.empty?
109
138
  end
110
139
 
111
140
  def initialize opts
@@ -119,6 +148,16 @@ class Person
119
148
  end
120
149
 
121
150
  class TestOptionInitializer < MiniTest::Unit::TestCase
151
+ def assert_raises x, &b
152
+ begin
153
+ b.call
154
+ assert false
155
+ rescue Exception => e
156
+ puts "#{e.class}: #{e}"
157
+ assert e.is_a?(x)
158
+ end
159
+ end
160
+
122
161
  def test_oi
123
162
  o = MyClass.aaa(1).bbb(2).ddd { 4 }.ccc(3).new(1, 2)
124
163
  assert_equal 1, o.options[:aaa]
@@ -129,11 +168,11 @@ class TestOptionInitializer < MiniTest::Unit::TestCase
129
168
  assert_equal 2, o.b
130
169
  assert_equal nil, o.y
131
170
 
132
- o = MyClass.aaa(1).bbb(2).ccc(3).aaa(4).new(1, 2, :ddd => 4) { :y }
171
+ o = MyClass.aaa(1).bbb(2).ccc(3).aaa(4).new(1, 2, :ddd => proc { 4 }) { :y }
133
172
  assert_equal 4, o.options[:aaa]
134
173
  assert_equal 2, o.options[:bbb]
135
174
  assert_equal 3, o.options[:ccc]
136
- assert_equal 4, o.options[:ddd]
175
+ assert_equal 4, o.options[:ddd].call
137
176
  assert_equal 1, o.a
138
177
  assert_equal 2, o.b
139
178
  assert_equal :y, o.y
@@ -146,9 +185,18 @@ class TestOptionInitializer < MiniTest::Unit::TestCase
146
185
  assert_raises(ArgumentError) { MyClass.aaa(1).new(1, 2, 3) }
147
186
  end
148
187
 
188
+ def test_default_1
189
+ MyClass.aaa(1)
190
+ assert_raises(ArgumentError) { MyClass.aaa { } }
191
+
192
+ MyClass.bbb(1)
193
+ assert_raises(ArgumentError) { MyClass.bbb { } }
194
+ end
195
+
149
196
  def test_method_missing
150
197
  assert_equal 2, MyClass2.aaa(1).bbb(2).num_options(true)
151
198
  assert_equal 2, MyClass2.aaa(1).bbb(2).echo(1) { |a| a * 2 }
199
+ assert_raises(NoMethodError) { MyClass2.aaa(1).bbb(2).echo? }
152
200
 
153
201
  assert_raises(NoMethodError) do
154
202
  MyClass3.aaa(1).bbb(2).echo(1) { |a| a * 2 }
@@ -169,37 +217,69 @@ class TestOptionInitializer < MiniTest::Unit::TestCase
169
217
 
170
218
  MyClass2.reset_count
171
219
  MyClass2.aaa(1).bbb(2)
172
- assert_equal 2 + 2, MyClass2.count
220
+ assert_equal 2 + 1, MyClass2.count
173
221
 
174
222
  MyClass2.reset_count
175
223
  MyClass2.aaa(1).bbb(2).new(:aaa => 3)
176
- assert_equal 2 + 2 + 2, MyClass2.count
224
+ assert_equal 2 + 1 + 2, MyClass2.count
177
225
 
178
226
  MyClass2.reset_count
179
227
  MyClass2.aaa(1).bbb(2).new
180
- assert_equal 2 + 2, MyClass2.count
228
+ assert_equal 2 + 1, MyClass2.count
181
229
 
182
230
  MyClass2.reset_count
183
231
  MyClass2.new :aaa => 1, :bbb => 2
184
- assert_equal 4, MyClass2.count
232
+ assert_equal 2 + 1, MyClass2.count
185
233
 
186
234
  assert_raises(TypeError) { MyClass2.new 'str' }
187
235
  end
188
236
 
189
237
  def test_varargs
190
- obj = MyClass4.two(1, 2).two_or_three(2, 3, 4).yet_two_or_three(3, 4, 5).b { :r }.new
238
+ obj = MyClassVarArgs.two(1, 2).two_or_three(2, 3, 4).yet_two_or_three(3, 4, 5).b { :r }.new
191
239
  assert_equal [1, 2], obj.options[:two]
192
240
  assert_equal [2, 3, 4], obj.options[:two_or_three]
193
241
  assert_equal [3, 4, 5], obj.options[:yet_two_or_three]
194
242
  assert_equal :r, obj.options[:b].call
195
- assert_raises(ArgumentError) { MyClass4.two(1) }
196
- assert_raises(ArgumentError) { MyClass4.two(1, 2) { } }
197
- assert_raises(ArgumentError) { MyClass4.two { } }
198
- assert_raises(ArgumentError) { MyClass4.two_or_three(1) }
199
- assert_raises(ArgumentError) { MyClass4.yet_two_or_three(1, 2, 3, 4) }
200
- assert_raises(ArgumentError) { MyClass4.yet_two_or_three {} }
201
- assert_raises(ArgumentError) { MyClass4.b(1) }
202
- assert_raises(ArgumentError) { MyClass4.b(1) {} }
243
+ assert_raises(ArgumentError) { MyClassVarArgs.two }
244
+ assert_raises(ArgumentError) { MyClassVarArgs.two(1) }
245
+ assert_raises(ArgumentError) { MyClassVarArgs.two(1, 2) { } }
246
+ assert_raises(ArgumentError) { MyClassVarArgs.two { } }
247
+ assert_raises(ArgumentError) { MyClassVarArgs.two_or_three(1) }
248
+ assert_raises(ArgumentError) { MyClassVarArgs.yet_two_or_three(1, 2, 3, 4) }
249
+ assert_raises(ArgumentError) { MyClassVarArgs.yet_two_or_three {} }
250
+ assert_raises(ArgumentError) { MyClassVarArgs.b(1) }
251
+ assert_raises(ArgumentError) { MyClassVarArgs.b(1) {} }
252
+ assert_raises(ArgumentError) { MyClassVarArgs.b(1) {} }
253
+ assert_equal [], MyClassVarArgs.v.new.options[:v]
254
+ assert_equal [1, 2, 3], MyClassVarArgs.v(1, 2, 3).new.options[:v]
255
+
256
+ MyClassVarArgs.class_eval do
257
+ option_initializer :b2 => :&
258
+ end
259
+ MyClassVarArgs.b2 {}
260
+ assert_raises(ArgumentError) { MyClassVarArgs.b2(5) }
261
+
262
+ MyClassVarArgs.class_eval do
263
+ option_initializer :b2
264
+ end
265
+ MyClassVarArgs.b2(5)
266
+ assert_raises(ArgumentError) { MyClassVarArgs.b2 {} }
267
+ end
268
+
269
+ def test_varargs_validate_options
270
+ assert_raises(TypeError) { MyClassVarArgs.new(:b => 1) }
271
+ assert_raises(ArgumentError) { MyClassVarArgs.new(:two => 1) }
272
+ assert_raises(ArgumentError) { MyClassVarArgs.new(:two => [1]) }
273
+ assert_raises(ArgumentError) { MyClassVarArgs.new(:two_or_three => 1) }
274
+ assert_raises(ArgumentError) { MyClassVarArgs.new(:two_or_three => [1]) }
275
+ assert_raises(ArgumentError) { MyClassVarArgs.new(:yet_two_or_three => [1]) }
276
+ assert_raises(ArgumentError) { MyClassVarArgs.new(:v => 1) }
277
+
278
+ opts = MyClassVarArgs.new(:two => [1, 2], :two_or_three => [2, 3, 4], :v => []).options
279
+
280
+ assert_equal [1, 2], opts[:two]
281
+ assert_equal [2, 3, 4], opts[:two_or_three]
282
+ assert_equal [], opts[:v]
203
283
  end
204
284
 
205
285
  def test_varargs_def
@@ -212,20 +292,102 @@ class TestOptionInitializer < MiniTest::Unit::TestCase
212
292
  assert_raises(ArgumentError) { MyClass5.class_eval { option_initializer :b => 0 } }
213
293
  assert_raises(ArgumentError) { MyClass5.class_eval { option_initializer :b => 3.14 } }
214
294
  assert_raises(ArgumentError) { MyClass5.class_eval { option_initializer :b => [1] } }
215
- assert_raises(ArgumentError) { MyClass5.class_eval { option_initializer :b => 0..3 } }
295
+ assert_raises(ArgumentError) { MyClass5.class_eval { option_initializer :b => -1..3 } }
216
296
  assert_raises(ArgumentError) { MyClass5.class_eval { option_initializer 3.14 } }
217
297
  assert_raises(ArgumentError) { MyClass5.class_eval { option_initializer 3.14 => nil } }
218
298
  assert_raises(ArgumentError) { MyClass5.class_eval { option_initializer :b => :block? } }
219
299
  end
220
300
 
301
+ def test_validator_block_arity
302
+ MyClass5.class_eval { option_validator { |k, v| } }
303
+ assert_raises(ArgumentError) { MyClass5.class_eval { option_validator { |v| } } }
304
+ MyClass5.class_eval { option_validator :aaa do |v| end }
305
+ assert_raises(ArgumentError) { MyClass5.class_eval { option_validator :aaa do |k, v| end } }
306
+ end
307
+
308
+ def test_typed_option
309
+ MyClassWithTypes.a(3)
310
+ assert_raises(TypeError) { MyClassWithTypes.a('str') }
311
+ assert_raises(TypeError) { MyClassWithTypes.b(1) }
312
+ assert_raises(ArgumentError) { MyClassWithTypes.c(1, 2) }
313
+ assert_raises(ArgumentError) { MyClassWithTypes.e(1) }
314
+ assert_raises(ArgumentError) { MyClassWithTypes.e(1, 'str') }
315
+ assert_raises(TypeError) { MyClassWithTypes.e(1, 'str', :array) }
316
+
317
+
318
+ assert_raises(TypeError) { MyClassWithTypes.new(:a => 'str') }
319
+ assert_raises(ArgumentError) { MyClassWithTypes.new(:e => :e) }
320
+ assert_raises(ArgumentError) { MyClassWithTypes.new(:e => []) }
321
+ assert_raises(TypeError) { MyClassWithTypes.new(:e => [1, 1, 1]) }
322
+
323
+ [
324
+ MyClassWithTypes.a(3).b('str').c(1).c(3.14).d([1, 2, 3]).e(1, 'str', [0, 1, 2]).options,
325
+ MyClassWithTypes.new(:a => 3, :b => 'str', :c => 3.14, :d => [1, 2, 3], :e => [1, 'str', [0, 1, 2]]).options
326
+ ].each do |opts|
327
+ assert_equal 3, opts[:a]
328
+ assert_equal 'str', opts[:b]
329
+ assert_equal 3.14, opts[:c]
330
+ assert_equal [1, 2, 3], opts[:d]
331
+ assert_equal [1, 'str', [0, 1, 2]], opts[:e]
332
+
333
+ end
334
+ end
335
+
336
+ def test_set
337
+ opts = MyClassWithTypes.f(true).g(false, 2).options
338
+ assert_equal true, opts[:f]
339
+ assert_equal [false, 2], opts[:g]
340
+
341
+ assert_raises(ArgumentError) { MyClassWithTypes.f(5) }
342
+ assert_raises(ArgumentError) { MyClassWithTypes.new(:f => 5) }
343
+ assert_raises(ArgumentError) { MyClassWithTypes.g(false, 10) }
344
+ assert_raises(ArgumentError) { MyClassWithTypes.g(nil, 2) }
345
+
346
+ assert_raises(ArgumentError) { MyClassWithTypes.class_eval { option_initializer :set => Set[] } }
347
+ end
348
+
221
349
  def test_readme
222
- john = Person.name('John Doe').birthday(1990, 1, 1).
350
+ john = Person.name('John Doe').birthday(1990, 1, 1).sex(:male).
223
351
  greetings { |name| "Hi, I'm #{name}!" }.id(1000).new
224
352
  john = Person.new :id => 1000, :name => 'John Doe',
225
353
  :birthday => [1990, 1, 1],
354
+ :sex => :male,
226
355
  :greetings => proc { |name| "Hi, I'm #{name}!" }
227
356
  Person.name('John Doe').birthday(1990, 1, 1).
228
357
  greetings { |name| "Hi, I'm #{name}!" }.id(1000).say_hello
229
358
  end
230
359
  end
231
360
 
361
+ class MyReadmeClass
362
+ include OptionInitializer
363
+
364
+ option_initializer :a, # Single object of any type
365
+ :b => 2, # Two objects of any type
366
+ :c => 1..3, # 1, 2, or 3 objects of any type
367
+ :d => :*, # Any number of objects
368
+ :e => :&, # Block
369
+ :f => Fixnum, # Single Fixnum object
370
+ :g => [Fixnum, String, Symbol] # Fixnum, String, and Symbol
371
+
372
+ # Validator for :f
373
+ option_validator :f do |v|
374
+ raise ArgumentError if v < 0
375
+ end
376
+
377
+ # Generic validator
378
+ option_validator do |k, v|
379
+ case k
380
+ when :a
381
+ # ...
382
+ when :b
383
+ # ...
384
+ else
385
+ end
386
+ end
387
+
388
+ def initialize options
389
+ validate_options options
390
+ @options = options
391
+ end
392
+ end
393
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: option_initializer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.5.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-16 00:00:00.000000000 Z
13
- dependencies: []
12
+ date: 2013-03-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: simplecov
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
14
30
  description: Object construction with method chaining
15
31
  email:
16
32
  - junegunn.c@gmail.com