option_initializer 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -15,11 +15,9 @@ require 'option_initializer'
15
15
 
16
16
  class Person
17
17
  include OptionInitializer
18
- option_initializer :id, :name, :age, :greetings
18
+ option_initializer :id, :name, :greetings => :block, :birthday => 1..3
19
19
  option_validator do |k, v|
20
20
  case k
21
- when :age
22
- raise ArgumentError, "invalid age" if v < 0
23
21
  when :name
24
22
  raise ArgumentError, "invalid name" if v.empty?
25
23
  end
@@ -38,7 +36,7 @@ end
38
36
  # Then
39
37
  john = Person.
40
38
  name('John Doe').
41
- age(19).
39
+ birthday(1990, 1, 1).
42
40
  greetings { |name| "Hi, I'm #{name}!" }.
43
41
  id(1000).
44
42
  new
@@ -47,7 +45,7 @@ john = Person.
47
45
  john = Person.new(
48
46
  :id => 1000,
49
47
  :name => 'John Doe',
50
- :age => 19,
48
+ :birthday => [1990, 1, 1],
51
49
  :greetings => proc { |name| "Hi, I'm #{name}!" }
52
50
  )
53
51
 
@@ -1,3 +1,3 @@
1
1
  module OptionInitializer
2
- VERSION = "1.2.0"
2
+ VERSION = "1.3.0"
3
3
  end
@@ -97,43 +97,74 @@ module OptionInitializer
97
97
  def base.option_initializer *syms
98
98
  oi = self.const_get(:OptionInitializing)
99
99
 
100
+ pairs = syms.inject([]) { |arr, sym|
101
+ case sym
102
+ when Symbol, String
103
+ arr << [sym.to_sym, 1]
104
+ when Hash
105
+ 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}"
108
+ end
109
+ [k.to_sym, v]
110
+ }
111
+ else
112
+ raise ArgumentError, "invalid option specification"
113
+ end
114
+ }
115
+
100
116
  # Class methods
101
- syms.each do |sym|
117
+ pairs.each do |pair|
118
+ sym = pair.first
119
+
102
120
  self.class_eval do
103
121
  # define_singleton_method not available on 1.8
104
122
  singleton = class << self; self end
105
123
  singleton.send :undef_method, sym if singleton.method_defined?(sym)
106
124
  singleton.send :define_method, sym do |*v, &b|
107
- if b && v.empty?
108
- oi.new self, {sym => b}, true
109
- elsif b && !v.empty?
110
- raise ArgumentError,
111
- "wrong number of arguments (#{v.length} for 0 when block given)"
112
- elsif v.length == 1
113
- oi.new self, {sym => v.first}, true
114
- else
115
- raise ArgumentError,
116
- "wrong number of arguments (#{v.length} for 1)"
117
- end
125
+ oi.new(self, {}, false).send(sym, *v, &b)
118
126
  end
119
127
  end
120
128
  end
121
129
 
122
130
  # Instance methods
123
131
  oi.class_eval do
124
- syms.each do |sym|
132
+ pairs.each do |pair|
133
+ sym, nargs = pair
125
134
  undef_method(sym) if method_defined?(sym)
126
135
  define_method(sym) do |*v, &b|
127
- if b && v.empty?
128
- merge(sym => b)
129
- elsif b && !v.empty?
130
- raise ArgumentError,
131
- "wrong number of arguments (#{v.length} for 0 when block given)"
132
- elsif v.length == 1
133
- merge(sym => v.first)
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?
149
+ 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
+ else
155
+ raise ArgumentError, "wrong number of arguments (#{v.length} for 1)"
156
+ 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})"
163
+ else
164
+ merge(sym => v)
165
+ end
134
166
  else
135
- raise ArgumentError,
136
- "wrong number of arguments (#{v.length} for 1)"
167
+ raise ArgumentError, "invalid option specification"
137
168
  end
138
169
  end
139
170
  end
@@ -79,13 +79,37 @@ class MyClass3
79
79
  end
80
80
  end
81
81
 
82
+ class MyClass4
83
+ attr_reader :options
84
+
85
+ include OptionInitializer
86
+ option_initializer :two => 2,
87
+ :two_or_three => 2..3,
88
+ :yet_two_or_three => 2...4,
89
+ :b => :block
90
+
91
+ def initialize options
92
+ validate_options @options = options
93
+ end
94
+ end
95
+
96
+ class MyClass5
97
+ include OptionInitializer
98
+ end
99
+
82
100
  # Excerpt from README
83
101
  class Person
84
102
  include OptionInitializer
85
- option_initializer :id, :name, :age, :greetings
86
- option_initializer!
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
109
+ end
87
110
 
88
111
  def initialize opts
112
+ validate_options opts
89
113
  @options = opts
90
114
  end
91
115
 
@@ -162,10 +186,46 @@ class TestOptionInitializer < MiniTest::Unit::TestCase
162
186
  assert_raises(TypeError) { MyClass2.new 'str' }
163
187
  end
164
188
 
189
+ 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
191
+ assert_equal [1, 2], obj.options[:two]
192
+ assert_equal [2, 3, 4], obj.options[:two_or_three]
193
+ assert_equal [3, 4, 5], obj.options[:yet_two_or_three]
194
+ 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) {} }
203
+ end
204
+
205
+ def test_varargs_def
206
+ assert_raises(NoMethodError) { MyClass5.a(1) }
207
+ MyClass5.class_eval do
208
+ option_initializer :a => 1...4
209
+ end
210
+ MyClass5.a(1)
211
+
212
+ assert_raises(ArgumentError) { MyClass5.class_eval { option_initializer :b => 0 } }
213
+ assert_raises(ArgumentError) { MyClass5.class_eval { option_initializer :b => 3.14 } }
214
+ assert_raises(ArgumentError) { MyClass5.class_eval { option_initializer :b => [1] } }
215
+ assert_raises(ArgumentError) { MyClass5.class_eval { option_initializer :b => 0..3 } }
216
+ assert_raises(ArgumentError) { MyClass5.class_eval { option_initializer 3.14 } }
217
+ assert_raises(ArgumentError) { MyClass5.class_eval { option_initializer 3.14 => nil } }
218
+ assert_raises(ArgumentError) { MyClass5.class_eval { option_initializer :b => :block? } }
219
+ end
220
+
165
221
  def test_readme
166
- john = Person.name('John Doe').age(19).greetings { |name| "Hi, I'm #{name}!" }.id(1000).new
167
- john = Person.new :id => 1000, :name => 'John Doe', :age => 19, :greetings => proc { |name| "Hi, I'm #{name}!" }
168
- Person.name('John Doe').age(19).greetings { |name| "Hi, I'm #{name}!" }.id(1000).say_hello
222
+ john = Person.name('John Doe').birthday(1990, 1, 1).
223
+ greetings { |name| "Hi, I'm #{name}!" }.id(1000).new
224
+ john = Person.new :id => 1000, :name => 'John Doe',
225
+ :birthday => [1990, 1, 1],
226
+ :greetings => proc { |name| "Hi, I'm #{name}!" }
227
+ Person.name('John Doe').birthday(1990, 1, 1).
228
+ greetings { |name| "Hi, I'm #{name}!" }.id(1000).say_hello
169
229
  end
170
230
  end
171
231
 
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.2.0
4
+ version: 1.3.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: 2013-03-04 00:00:00.000000000 Z
12
+ date: 2013-03-16 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Object construction with method chaining
15
15
  email: