option_initializer 1.5.0 → 1.5.1

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
@@ -17,10 +17,10 @@ class Person
17
17
  include OptionInitializer
18
18
 
19
19
  option_initializer :id,
20
- :name => String,
20
+ :name => String,
21
21
  :greetings => :&,
22
- :birthday => 1..3,
23
- :sex => Set[:male, :female]
22
+ :birthday => 1..3,
23
+ :sex => Set[:male, :female]
24
24
 
25
25
  option_validator :name do |v|
26
26
  raise ArgumentError, "invalid name" if v.empty?
@@ -78,7 +78,7 @@ class MyClass
78
78
  :c => 1..3, # 1, 2, or 3 objects of any type
79
79
  :d => :*, # Any number of objects of any type
80
80
  :e => :&, # Block
81
- :f => Fixnum, # Single Fixnum object
81
+ :f => Fixnum | Range, # Single Fixnum or Range object
82
82
  :g => [Fixnum, String, Symbol], # Fixnum, String, and Symbol
83
83
  :h => Set[true, false], # Value must be either true or false
84
84
  :i => [Fixnum, Set[true, false]] # Fixnum and boolean
@@ -1,57 +1,94 @@
1
1
  require 'option_initializer/version'
2
2
  require 'set'
3
3
 
4
- module OptionInitializer
5
- class OptionInitializingTemplate
6
- attr_reader :options
7
- alias to_h options
8
-
9
- def initialize base, options, need_validation
10
- validate options if need_validation
11
- @base = base
12
- @options = options
4
+ unless Class.respond_to?(:|)
5
+ class Class
6
+ def | other_class
7
+ unless other_class.is_a?(Class)
8
+ raise TypeError, "wrong argument type (expected: Class)"
9
+ end
10
+ OptionInitializer::ClassMatch.new(self, other_class)
13
11
  end
12
+ end
13
+ else
14
+ Kernel.warn "Class already has `|' method. OptionInitializer will not override its behavior."
15
+ end
14
16
 
15
- def new *args, &block
16
- args = args.dup
17
- opts = @options
17
+ # @private
18
+ class OptionInitializingTemplate
19
+ attr_reader :options
20
+ alias to_h options
18
21
 
19
- # Convention. Deal with it.
20
- if args.last.is_a?(Hash)
21
- validate args.last
22
- opts = opts.merge(args.last)
23
- args.pop
24
- else
25
- opts = opts.dup
26
- end
22
+ def initialize base, options, need_validation
23
+ validate options if need_validation
24
+ @base = base
25
+ @options = options
26
+ end
27
27
 
28
- opts.instance_eval do
29
- def option_validated?
30
- true
31
- end
28
+ def new *args, &block
29
+ args = args.dup
30
+ opts = @options
31
+
32
+ # Convention. Deal with it.
33
+ if args.last.is_a?(Hash)
34
+ validate args.last
35
+ opts = opts.merge(args.last)
36
+ args.pop
37
+ else
38
+ opts = opts.dup
39
+ end
40
+
41
+ opts.instance_eval do
42
+ def option_validated?
43
+ true
32
44
  end
33
- args << opts
45
+ end
46
+ args << opts
34
47
 
35
- @base.new(*args, &block)
48
+ @base.new(*args, &block)
49
+ end
50
+
51
+ def merge opts
52
+ validate opts
53
+ self.class.new @base, @options.merge(opts), false
54
+ end
55
+
56
+ def validate hash
57
+ avals, vals = [:ARG_VALIDATORS, :VALIDATORS].map { |s|
58
+ self.class.const_get(s)
59
+ }
60
+ hash.each do |k, v|
61
+ avals[k] && avals[k].call(v)
62
+ vals[k] && vals[k].call(v)
63
+ vals[nil] && vals[nil].call(k, v)
36
64
  end
65
+ end
66
+ end
37
67
 
38
- def merge opts
39
- validate opts
40
- self.class.new @base, @options.merge(opts), false
68
+ module OptionInitializer
69
+ class ClassMatch
70
+ def initialize *classes
71
+ @classes = Set[*classes]
41
72
  end
42
73
 
43
- def validate hash
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)
74
+ def | other_class
75
+ unless other_class.is_a?(Class)
76
+ raise TypeError, "wrong argument type (expected: Class)"
51
77
  end
78
+ ClassMatch.new(*@classes.union([other_class]))
79
+ end
80
+
81
+ def match object
82
+ @classes.any? { |k| object.is_a? k }
83
+ end
84
+
85
+ def to_s
86
+ a = @classes.map(&:to_s)
87
+ [a[0...-1].join(', '), a.last].reject(&:empty?).join(', or ')
52
88
  end
53
89
  end
54
90
 
91
+ # @private
55
92
  module MethodCallShortcut
56
93
  def method_missing sym, *args, &block
57
94
  # 1.8
@@ -79,6 +116,7 @@ module OptionInitializer
79
116
  options
80
117
  end
81
118
 
119
+ # @private
82
120
  def self.included base
83
121
  unless base.constants.map(&:to_sym).include?(:OptionInitializing)
84
122
  base.const_set :OptionInitializing, oi = OptionInitializingTemplate.dup
@@ -120,9 +158,13 @@ module OptionInitializer
120
158
  when Set
121
159
  raise ArgumentError, "empty set of values specified for #{k}" if v.length == 0
122
160
  when Array
123
- raise ArgumentError, "invalid option definition: `#{v}'" unless v.all? { |e| e.is_a?(Class) || e.is_a?(Set) }
161
+ unless v.all? { |e| [Class, Set, ClassMatch].any? { |kl| e.is_a?(kl) } }
162
+ raise ArgumentError, "invalid option definition: `#{v}'"
163
+ end
124
164
  when Class, :*, :&
125
165
  # noop
166
+ when ClassMatch
167
+ # noop
126
168
  else
127
169
  raise ArgumentError, "invalid option definition: `#{v}'"
128
170
  end
@@ -191,6 +233,10 @@ module OptionInitializer
191
233
  unless c.include?(e)
192
234
  raise ArgumentError, "invalid option value: `#{e}' (expected one of #{c.to_a.inspect})"
193
235
  end
236
+ when ClassMatch
237
+ unless c.match e
238
+ raise TypeError, "wrong argument type #{e.class} (expected #{c})"
239
+ end
194
240
  end
195
241
  end
196
242
  end
@@ -201,6 +247,12 @@ module OptionInitializer
201
247
  raise TypeError, "wrong argument type #{v.class} (expected #{nargs})"
202
248
  end
203
249
  }
250
+ when ClassMatch
251
+ vals[sym] = proc { |v|
252
+ unless nargs.match v
253
+ raise TypeError, "wrong argument type #{v.class} (expected #{nargs})"
254
+ end
255
+ }
204
256
  end
205
257
  end
206
258
 
@@ -234,7 +286,7 @@ module OptionInitializer
234
286
  raise ArgumentError, "block not expected"
235
287
  else
236
288
  case nargs
237
- when 1, Class, Set
289
+ when 1, Class, Set, ClassMatch
238
290
  if v.length == 1
239
291
  merge(sym => v.first)
240
292
  else
@@ -1,3 +1,3 @@
1
1
  module OptionInitializer
2
- VERSION = "1.5.0"
2
+ VERSION = "1.5.1"
3
3
  end
@@ -18,4 +18,5 @@ Gem::Specification.new do |gem|
18
18
  gem.require_paths = ["lib"]
19
19
 
20
20
  gem.add_development_dependency 'simplecov'
21
+ gem.add_development_dependency 'minitest'
21
22
  end
@@ -122,6 +122,19 @@ class MyClassWithTypes
122
122
  end
123
123
  end
124
124
 
125
+ class MyClassWithClassOrOperator
126
+ include OptionInitializer
127
+ option_initializer :a => Fixnum | Float | Range,
128
+ :b => String,
129
+ :c => [String | Symbol, Numeric]
130
+
131
+ attr_reader :options
132
+ def initialize options
133
+ validate_options options
134
+ @options = options
135
+ end
136
+ end
137
+
125
138
  # Excerpt from README
126
139
  class Person
127
140
  include OptionInitializer
@@ -356,6 +369,21 @@ class TestOptionInitializer < MiniTest::Unit::TestCase
356
369
  Person.name('John Doe').birthday(1990, 1, 1).
357
370
  greetings { |name| "Hi, I'm #{name}!" }.id(1000).say_hello
358
371
  end
372
+
373
+ def test_disjunctive_class
374
+ init = MyClassWithClassOrOperator.a(1).a(1..2).a(3.14).b('hello').c(:hello, 100)
375
+ [init, init.new].each do |obj|
376
+ assert_equal 3.14, obj.options[:a]
377
+ assert_equal 'hello', obj.options[:b]
378
+ assert_equal [:hello, 100], obj.options[:c]
379
+ end
380
+ assert_raises(TypeError) { MyClassWithClassOrOperator.a(:hello) }
381
+ assert_raises(TypeError) { MyClassWithClassOrOperator.b(1) }
382
+ assert_raises(TypeError) { MyClassWithClassOrOperator.c(1, 1) }
383
+ assert_raises(TypeError) { MyClassWithClassOrOperator.new(:a => :hello) }
384
+ assert_raises(TypeError) { MyClassWithClassOrOperator.new(:b => 1) }
385
+ assert_raises(TypeError) { MyClassWithClassOrOperator.new(:c => [1, 1]) }
386
+ end
359
387
  end
360
388
 
361
389
  class MyReadmeClass
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.5.0
4
+ version: 1.5.1
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: 2013-03-18 00:00:00.000000000 Z
12
+ date: 2013-04-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: simplecov
@@ -27,6 +27,22 @@ dependencies:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: minitest
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
30
46
  description: Object construction with method chaining
31
47
  email:
32
48
  - junegunn.c@gmail.com