functional-ruby 0.7.2 → 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
data/md/utilities.md CHANGED
@@ -1,55 +1,55 @@
1
- # Utility Functions
2
-
3
- Convenience functions are not imported by default. They need a separate `require` statement:
4
-
5
- ```ruby
6
- require 'functional/utilities'
7
- ```
8
-
9
- This gives you access to a few constants and functions:
10
-
11
- ```ruby
12
- Infinity #=> Infinity
13
- NaN #=> NaN
14
-
15
- repl? #=> true when called under irb, pry, bundle console, or rails console
16
-
17
- safe(1, 2){|a, b| a + b} #=> 3
18
- safe{ eval 'puts "Hello World!"' } #=> SecurityError: Insecure operation
19
-
20
- pp_s [1,2,3,4] #=> "[1, 2, 3, 4]\n" props to Rha7
21
-
22
- delta(-1, 1) #=> 2
23
- delta({count: -1}, {count: 1}){|item| item[:count]} #=> 2
24
-
25
- repeatedly(10, 1){|previous| previous * 2 } #=> [2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
26
- ```
27
-
28
- ## Copyright
29
-
30
- *Functional Ruby* is Copyright © 2013 [Jerry D'Antonio](https://twitter.com/jerrydantonio).
31
- It is free software and may be redistributed under the terms specified in the LICENSE file.
32
-
33
- ## License
34
-
35
- Released under the MIT license.
36
-
37
- http://www.opensource.org/licenses/mit-license.php
38
-
39
- > Permission is hereby granted, free of charge, to any person obtaining a copy
40
- > of this software and associated documentation files (the "Software"), to deal
41
- > in the Software without restriction, including without limitation the rights
42
- > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
43
- > copies of the Software, and to permit persons to whom the Software is
44
- > furnished to do so, subject to the following conditions:
45
- >
46
- > The above copyright notice and this permission notice shall be included in
47
- > all copies or substantial portions of the Software.
48
- >
49
- > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
50
- > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
51
- > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
52
- > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
53
- > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
54
- > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
55
- > THE SOFTWARE.
1
+ # Utility Functions
2
+
3
+ Convenience functions are not imported by default. They need a separate `require` statement:
4
+
5
+ ```ruby
6
+ require 'functional/utilities'
7
+ ```
8
+
9
+ This gives you access to a few constants and functions:
10
+
11
+ ```ruby
12
+ Infinity #=> Infinity
13
+ NaN #=> NaN
14
+
15
+ repl? #=> true when called under irb, pry, bundle console, or rails console
16
+
17
+ safe(1, 2){|a, b| a + b} #=> 3
18
+ safe{ eval 'puts "Hello World!"' } #=> SecurityError: Insecure operation
19
+
20
+ pp_s [1,2,3,4] #=> "[1, 2, 3, 4]\n" props to Rha7
21
+
22
+ delta(-1, 1) #=> 2
23
+ delta({count: -1}, {count: 1}){|item| item[:count]} #=> 2
24
+
25
+ repeatedly(10, 1){|previous| previous * 2 } #=> [2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
26
+ ```
27
+
28
+ ## Copyright
29
+
30
+ *Functional Ruby* is Copyright © 2013 [Jerry D'Antonio](https://twitter.com/jerrydantonio).
31
+ It is free software and may be redistributed under the terms specified in the LICENSE file.
32
+
33
+ ## License
34
+
35
+ Released under the MIT license.
36
+
37
+ http://www.opensource.org/licenses/mit-license.php
38
+
39
+ > Permission is hereby granted, free of charge, to any person obtaining a copy
40
+ > of this software and associated documentation files (the "Software"), to deal
41
+ > in the Software without restriction, including without limitation the rights
42
+ > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
43
+ > copies of the Software, and to permit persons to whom the Software is
44
+ > furnished to do so, subject to the following conditions:
45
+ >
46
+ > The above copyright notice and this permission notice shall be included in
47
+ > all copies or substantial portions of the Software.
48
+ >
49
+ > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
50
+ > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
51
+ > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
52
+ > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
53
+ > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
54
+ > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
55
+ > THE SOFTWARE.
@@ -1,464 +1,508 @@
1
- require 'spec_helper'
2
-
3
- describe '-behavior' do
4
-
5
- before(:each) do
6
- @__behavior_info__ = $__behavior_info__
7
- $__behavior_info__ = {}
8
- end
9
-
10
- after(:each) do
11
- $__behavior_info__ = @__behavior_info__
12
- end
13
-
14
- context 'behavior_info/2' do
15
-
16
- it 'accepts a symbol name' do
17
- behavior_info(:gen_foo, foo: 0)
18
- $__behavior_info__.keys.first.should eq :gen_foo
19
- end
20
-
21
- it 'accepts a string name' do
22
- behavior_info('gen_foo', foo: 0)
23
- $__behavior_info__.keys.first.should eq :gen_foo
24
- end
25
-
26
- it 'accepts zero function names' do
27
- behavior_info(:gen_foo)
28
- $__behavior_info__.keys.first.should eq :gen_foo
29
- end
30
-
31
- it 'accepts symbols for function names' do
32
- behavior_info(:gen_foo, foo: 0)
33
- $__behavior_info__.values.first.should == {foo: 0}
34
- end
35
-
36
- it 'accepts strings as function names' do
37
- behavior_info(:gen_foo, 'foo' => 0)
38
- $__behavior_info__.values.first.should == {foo: 0}
39
- end
40
-
41
- it 'accepts numeric arity values' do
42
- behavior_info(:gen_foo, foo: 0)
43
- $__behavior_info__.values.first.should == {foo: 0}
44
- end
45
-
46
- it 'accepts :any as an arity value' do
47
- behavior_info(:gen_foo, foo: :any)
48
- $__behavior_info__.values.first.should == {foo: :any}
49
- end
50
- end
51
-
52
- context 'behavior/1' do
53
-
54
- it 'raises an exception if the behavior has not been defined' do
55
- lambda {
56
- Class.new{
57
- behavior(:gen_foo)
58
- }
59
- }.should raise_error(BehaviorError)
60
- end
61
-
62
- it 'can be called multiple times for one class' do
63
- behavior_info(:gen_foo, foo: 0)
64
- behavior_info(:gen_bar, bar: 0)
65
-
66
- lambda {
67
- Class.new{
68
- behavior(:gen_foo)
69
- behavior(:gen_bar)
70
- }
71
- }.should_not raise_error
72
- end
73
- end
74
-
75
- context 'object creation' do
76
-
77
- it 'checks all required behaviors' do
78
- behavior_info(:gen_foo, foo: 0)
79
- behavior_info(:gen_bar, bar: 1)
80
-
81
- clazz = Class.new {
82
- behavior(:gen_foo)
83
- behavior(:gen_bar)
84
- def foo() nil; end
85
- }
86
- lambda{ clazz.new }.should raise_error(BehaviorError)
87
-
88
- clazz = Class.new {
89
- behavior(:gen_foo)
90
- behavior(:gen_bar)
91
- def bar() nil; end
92
- }
93
- lambda{ clazz.new }.should raise_error(BehaviorError)
94
-
95
- clazz = Class.new {
96
- behavior(:gen_foo)
97
- behavior(:gen_bar)
98
- }
99
- lambda{ clazz.new }.should raise_error(BehaviorError)
100
- end
101
-
102
- context 'instance methods' do
103
-
104
- it 'raises an exception when one or more function definitions are missing' do
105
- behavior_info(:gen_foo, foo: 0, bar: 1)
106
- clazz = Class.new {
107
- behavior(:gen_foo)
108
- def foo() nil; end
109
- }
110
-
111
- lambda {
112
- clazz.new
113
- }.should raise_error(BehaviorError)
114
- end
115
-
116
- it 'raises an exception when one or more functions do not have proper arity' do
117
- behavior_info(:gen_foo, foo: 0)
118
- clazz = Class.new {
119
- behavior(:gen_foo)
120
- def foo(broken) nil; end
121
- }
122
-
123
- lambda {
124
- clazz.new
125
- }.should raise_error(BehaviorError)
126
- end
127
-
128
- it 'accepts any arity when function arity is set to :any' do
129
- behavior_info(:gen_foo, foo: :any)
130
- clazz = Class.new {
131
- behavior(:gen_foo)
132
- def foo(first) nil; end
133
- }
134
-
135
- lambda {
136
- clazz.new
137
- }.should_not raise_error
138
- end
139
-
140
- it 'creates the object when function definitions match' do
141
- behavior_info(:gen_foo, foo: 0, bar: 1)
142
- clazz = Class.new {
143
- behavior(:gen_foo)
144
- def foo() nil; end
145
- def bar(first) nil; end
146
- }
147
-
148
- lambda {
149
- clazz.new
150
- }.should_not raise_error
151
- end
152
- end
153
-
154
- context 'class methods' do
155
-
156
- it 'raises an exception when one or more function definitions are missing' do
157
- behavior_info(:gen_foo, self_foo: 0, self_bar: 1)
158
- clazz = Class.new {
159
- behavior(:gen_foo)
160
- def self.foo() nil; end
161
- }
162
-
163
- lambda {
164
- clazz.new
165
- }.should raise_error(BehaviorError)
166
- end
167
-
168
- it 'raises an exception when one or more functions do not have proper arity' do
169
- behavior_info(:gen_foo, self_foo: 0)
170
- clazz = Class.new {
171
- behavior(:gen_foo)
172
- def self.foo(broken) nil; end
173
- }
174
-
175
- lambda {
176
- clazz.new
177
- }.should raise_error(BehaviorError)
178
- end
179
-
180
- it 'accepts any arity when function arity is set to :any' do
181
- behavior_info(:gen_foo, self_foo: :any)
182
- clazz = Class.new {
183
- behavior(:gen_foo)
184
- def self.foo(first) nil; end
185
- }
186
-
187
- lambda {
188
- clazz.new
189
- }.should_not raise_error
190
- end
191
-
192
- it 'creates the object when function definitions match' do
193
- behavior_info(:gen_foo, self_foo: 0, self_bar: 1)
194
- clazz = Class.new {
195
- behavior(:gen_foo)
196
- def self.foo() nil; end
197
- def self.bar(first) nil; end
198
- }
199
-
200
- lambda {
201
- clazz.new
202
- }.should_not raise_error
203
- end
204
- end
205
-
206
- context 'inheritance' do
207
-
208
- it 'raises an exception if a superclass includes a behavior the subclass does not support' do
209
- behavior_info(:gen_foo, foo: 0)
210
- superclass = Class.new{
211
- behavior(:gen_foo)
212
- }
213
- subclass = Class.new(superclass)
214
-
215
- lambda {
216
- subclass.new
217
- }.should raise_error(BehaviorError)
218
- end
219
-
220
- it 'raises an exception if a module includes a behavior the containing class does not support' do
221
- behavior_info(:gen_foo, foo: 0)
222
- mod = Module.new{
223
- behavior(:gen_foo)
224
- }
225
- subclass = Class.new{
226
- include mod
227
- }
228
-
229
- lambda {
230
- subclass.new
231
- }.should raise_error(BehaviorError)
232
- end
233
-
234
- it 'supports behaviors from multiple ancestors' do
235
- behavior_info(:gen_foo, foo: 0)
236
- behavior_info(:gen_bar, bar: 0)
237
- behavior_info(:gen_baz, baz: 0)
238
-
239
- rootclass = Class.new{ behavior(:gen_foo) }
240
- superclass = Class.new(rootclass){ behavior(:gen_bar) }
241
-
242
- subclass = Class.new(superclass){
243
- behavior(:gen_baz)
244
- def bar() nil; end
245
- def baz() nil; end
246
- }
247
- lambda {
248
- subclass.new
249
- }.should raise_error(BehaviorError)
250
-
251
- subclass = Class.new(superclass){
252
- behavior(:gen_baz)
253
- def foo() nil; end
254
- def baz() nil; end
255
- }
256
- lambda {
257
- subclass.new
258
- }.should raise_error(BehaviorError)
259
-
260
- subclass = Class.new(superclass){
261
- behavior(:gen_baz)
262
- def foo() nil; end
263
- def bar() nil; end
264
- }
265
- lambda {
266
- subclass.new
267
- }.should raise_error(BehaviorError)
268
-
269
- subclass = Class.new(superclass){
270
- behavior(:gen_baz)
271
- def foo() nil; end
272
- def bar() nil; end
273
- def baz() nil; end
274
- }
275
- lambda {
276
- subclass.new
277
- }.should_not raise_error
278
- end
279
-
280
- it 'supports multiple behaviors in an included module' do
281
- behavior_info(:gen_foo, foo: 0)
282
- behavior_info(:gen_bar, bar: 0)
283
- behavior_info(:gen_baz, baz: 0)
284
-
285
- mod = Module.new{
286
- behavior(:gen_foo)
287
- behavior(:gen_bar)
288
- behavior(:gen_baz)
289
- }
290
-
291
- subclass = Class.new{
292
- include mod
293
- def bar() nil; end
294
- def baz() nil; end
295
- }
296
- lambda {
297
- subclass.new
298
- }.should raise_error(BehaviorError)
299
-
300
- subclass = Class.new{
301
- include mod
302
- def foo() nil; end
303
- def baz() nil; end
304
- }
305
- lambda {
306
- subclass.new
307
- }.should raise_error(BehaviorError)
308
-
309
- subclass = Class.new{
310
- include mod
311
- def foo() nil; end
312
- def bar() nil; end
313
- }
314
- lambda {
315
- subclass.new
316
- }.should raise_error(BehaviorError)
317
-
318
- subclass = Class.new{
319
- include mod
320
- def foo() nil; end
321
- def bar() nil; end
322
- def baz() nil; end
323
- }
324
- lambda {
325
- subclass.new
326
- }.should_not raise_error
327
- end
328
- end
329
- end
330
-
331
- context '#behaves_as?' do
332
-
333
- it 'returns false when the behavior does not exist' do
334
- clazz = Class.new { }
335
- clazz.new.behaves_as?(:gen_foo).should be_false
336
- end
337
-
338
- it 'accepts behavior name as a symbol' do
339
- behavior_info(:gen_foo)
340
- clazz = Class.new { }
341
- clazz.new.behaves_as?(:gen_foo).should be_true
342
- end
343
-
344
- it 'accepts behavior name as a string' do
345
- behavior_info(:gen_foo)
346
- clazz = Class.new { }
347
- clazz.new.behaves_as?('gen_foo').should be_true
348
- end
349
-
350
- context 'Object' do
351
-
352
- it 'returns true when the behavior is fully suported' do
353
- behavior_info(:gen_foo, foo: 0, bar: 1, baz: 2)
354
- clazz = Class.new {
355
- def foo() nil; end
356
- def bar(first) nil; end
357
- def baz(first, second) nil; end
358
- }
359
-
360
- clazz.new.behaves_as?(:gen_foo).should be_true
361
- end
362
-
363
- it 'accepts any arity when function arity is set to :any' do
364
- behavior_info(:gen_foo, foo: :any)
365
- clazz = Class.new {
366
- def foo(*args, &block) nil; end
367
- }
368
-
369
- clazz.new.behaves_as?(:gen_foo).should be_true
370
- end
371
-
372
- it 'returns false when the behavior is partially supported' do
373
- behavior_info(:gen_foo, foo: 0, bar: 1, baz: 2)
374
- clazz = Class.new {
375
- def foo() nil; end
376
- def bar(first) nil; end
377
- }
378
-
379
- clazz.new.behaves_as?(:gen_foo).should be_false
380
- end
381
-
382
- it 'returns false when the behavior is not supported at all' do
383
- behavior_info(:gen_foo, foo: 0, bar: 1, baz: 2)
384
- clazz = Class.new { }
385
- clazz.new.behaves_as?(:gen_foo).should be_false
386
- end
387
- end
388
-
389
- context 'Class' do
390
-
391
- it 'returns true when the behavior is fully suported' do
392
- behavior_info(:gen_foo, self_foo: 0, self_bar: 1, baz: 2)
393
- clazz = Class.new {
394
- def self.foo() nil; end
395
- def self.bar(first) nil; end
396
- def baz(first, second) nil; end
397
- }
398
-
399
- clazz.behaves_as?(:gen_foo).should be_true
400
- clazz.new.behaves_as?(:gen_foo).should be_true
401
- end
402
-
403
- it 'accepts any arity when function arity is set to :any' do
404
- behavior_info(:gen_foo, self_foo: :any)
405
- clazz = Class.new {
406
- def self.foo(*args, &block) nil; end
407
- }
408
-
409
- clazz.behaves_as?(:gen_foo).should be_true
410
- clazz.new.behaves_as?(:gen_foo).should be_true
411
- end
412
-
413
- it 'returns false when the behavior is partially supported' do
414
- behavior_info(:gen_foo, self_foo: 0, bar: 1, self_baz: 2)
415
- clazz = Class.new {
416
- def self.foo() nil; end
417
- def self(first) nil; end
418
- }
419
-
420
- clazz.behaves_as?(:gen_foo).should be_false
421
- clazz.new.behaves_as?(:gen_foo).should be_false
422
- end
423
-
424
- it 'returns false when the behavior is not supported at all' do
425
- behavior_info(:gen_foo, self_foo: 0, self_bar: 1, self_baz: 2)
426
- clazz = Class.new { }
427
- clazz.new.behaves_as?(:gen_foo).should be_false
428
- end
429
- end
430
- end
431
-
432
- context 'aliases' do
433
-
434
- it 'aliases behaviour_info for behavior_info' do
435
- behaviour_info(:gen_foo)
436
- clazz = Class.new { }
437
- clazz.new.behaves_as?(:gen_foo).should be_true
438
- end
439
-
440
- it 'aliases interface for behavior_info' do
441
- interface(:gen_foo)
442
- clazz = Class.new { }
443
- clazz.new.behaves_as?(:gen_foo).should be_true
444
- end
445
-
446
- it 'aliases behaviour for behavior' do
447
- behavior_info(:gen_foo, foo: 0)
448
- clazz = Class.new {
449
- behaviour(:gen_foo)
450
- def foo() nil; end
451
- }
452
- clazz.new.behaves_as?(:gen_foo).should be_true
453
- end
454
-
455
- it 'aliases behaves_as for behavior' do
456
- behavior_info(:gen_foo, foo: 0)
457
- clazz = Class.new {
458
- behaves_as :gen_foo
459
- def foo() nil; end
460
- }
461
- clazz.new.behaves_as?(:gen_foo).should be_true
462
- end
463
- end
464
- end
1
+ require 'spec_helper'
2
+
3
+ describe '-behavior' do
4
+
5
+ before(:each) do
6
+ @__behavior_info__ = $__behavior_info__
7
+ $__behavior_info__ = {}
8
+ end
9
+
10
+ after(:each) do
11
+ $__behavior_info__ = @__behavior_info__
12
+ end
13
+
14
+ context 'behavior_info/2' do
15
+
16
+ it 'accepts a symbol name' do
17
+ behavior_info(:gen_foo, foo: 0)
18
+ $__behavior_info__.keys.first.should eq :gen_foo
19
+ end
20
+
21
+ it 'accepts a string name' do
22
+ behavior_info('gen_foo', foo: 0)
23
+ $__behavior_info__.keys.first.should eq :gen_foo
24
+ end
25
+
26
+ it 'accepts zero function names' do
27
+ behavior_info(:gen_foo)
28
+ $__behavior_info__.keys.first.should eq :gen_foo
29
+ end
30
+
31
+ it 'accepts symbols for function names' do
32
+ behavior_info(:gen_foo, foo: 0)
33
+ $__behavior_info__.values.first.should == {foo: 0}
34
+ end
35
+
36
+ it 'accepts strings as function names' do
37
+ behavior_info(:gen_foo, 'foo' => 0)
38
+ $__behavior_info__.values.first.should == {foo: 0}
39
+ end
40
+
41
+ it 'accepts numeric arity values' do
42
+ behavior_info(:gen_foo, foo: 0)
43
+ $__behavior_info__.values.first.should == {foo: 0}
44
+ end
45
+
46
+ it 'accepts :any as an arity value' do
47
+ behavior_info(:gen_foo, foo: :any)
48
+ $__behavior_info__.values.first.should == {foo: :any}
49
+ end
50
+ end
51
+
52
+ context 'behavior/1' do
53
+
54
+ it 'raises an exception if the behavior has not been defined' do
55
+ lambda {
56
+ Class.new{
57
+ behavior(:gen_foo)
58
+ }
59
+ }.should raise_error(BehaviorError)
60
+ end
61
+
62
+ it 'can be called multiple times for one class' do
63
+ behavior_info(:gen_foo, foo: 0)
64
+ behavior_info(:gen_bar, bar: 0)
65
+
66
+ lambda {
67
+ Class.new{
68
+ behavior(:gen_foo)
69
+ behavior(:gen_bar)
70
+ }
71
+ }.should_not raise_error
72
+ end
73
+ end
74
+
75
+ context 'object creation' do
76
+
77
+ it 'checks all required behaviors' do
78
+ behavior_info(:gen_foo, foo: 0)
79
+ behavior_info(:gen_bar, bar: 1)
80
+
81
+ clazz = Class.new {
82
+ behavior(:gen_foo)
83
+ behavior(:gen_bar)
84
+ def foo() nil; end
85
+ }
86
+ lambda{ clazz.new }.should raise_error(BehaviorError)
87
+
88
+ clazz = Class.new {
89
+ behavior(:gen_foo)
90
+ behavior(:gen_bar)
91
+ def bar() nil; end
92
+ }
93
+ lambda{ clazz.new }.should raise_error(BehaviorError)
94
+
95
+ clazz = Class.new {
96
+ behavior(:gen_foo)
97
+ behavior(:gen_bar)
98
+ }
99
+ lambda{ clazz.new }.should raise_error(BehaviorError)
100
+ end
101
+
102
+ context 'instance methods' do
103
+
104
+ it 'raises an exception when one or more function definitions are missing' do
105
+ behavior_info(:gen_foo, foo: 0, bar: 1)
106
+ clazz = Class.new {
107
+ behavior(:gen_foo)
108
+ def foo() nil; end
109
+ }
110
+
111
+ lambda {
112
+ clazz.new
113
+ }.should raise_error(BehaviorError)
114
+ end
115
+
116
+ it 'raises an exception when one or more functions do not have proper arity' do
117
+ behavior_info(:gen_foo, foo: 0)
118
+ clazz = Class.new {
119
+ behavior(:gen_foo)
120
+ def foo(broken) nil; end
121
+ }
122
+
123
+ lambda {
124
+ clazz.new
125
+ }.should raise_error(BehaviorError)
126
+ end
127
+
128
+ it 'accepts any arity when function arity is set to :any' do
129
+ behavior_info(:gen_foo, foo: :any)
130
+ clazz = Class.new {
131
+ behavior(:gen_foo)
132
+ def foo(first) nil; end
133
+ }
134
+
135
+ lambda {
136
+ clazz.new
137
+ }.should_not raise_error
138
+ end
139
+
140
+ it 'creates the object when function definitions match' do
141
+ behavior_info(:gen_foo, foo: 0, bar: 1)
142
+ clazz = Class.new {
143
+ behavior(:gen_foo)
144
+ def foo() nil; end
145
+ def bar(first) nil; end
146
+ }
147
+
148
+ lambda {
149
+ clazz.new
150
+ }.should_not raise_error
151
+ end
152
+ end
153
+
154
+ context 'class methods' do
155
+
156
+ it 'raises an exception when one or more function definitions are missing' do
157
+ behavior_info(:gen_foo, self_foo: 0, self_bar: 1)
158
+ clazz = Class.new {
159
+ behavior(:gen_foo)
160
+ def self.foo() nil; end
161
+ }
162
+
163
+ lambda {
164
+ clazz.new
165
+ }.should raise_error(BehaviorError)
166
+ end
167
+
168
+ it 'raises an exception when one or more functions do not have proper arity' do
169
+ behavior_info(:gen_foo, self_foo: 0)
170
+ clazz = Class.new {
171
+ behavior(:gen_foo)
172
+ def self.foo(broken) nil; end
173
+ }
174
+
175
+ lambda {
176
+ clazz.new
177
+ }.should raise_error(BehaviorError)
178
+ end
179
+
180
+ it 'accepts any arity when function arity is set to :any' do
181
+ behavior_info(:gen_foo, self_foo: :any)
182
+ clazz = Class.new {
183
+ behavior(:gen_foo)
184
+ def self.foo(first) nil; end
185
+ }
186
+
187
+ lambda {
188
+ clazz.new
189
+ }.should_not raise_error
190
+ end
191
+
192
+ it 'creates the object when function definitions match' do
193
+ behavior_info(:gen_foo, self_foo: 0, self_bar: 1)
194
+ clazz = Class.new {
195
+ behavior(:gen_foo)
196
+ def self.foo() nil; end
197
+ def self.bar(first) nil; end
198
+ }
199
+
200
+ lambda {
201
+ clazz.new
202
+ }.should_not raise_error
203
+ end
204
+ end
205
+
206
+ context 'inheritance' do
207
+
208
+ it 'raises an exception if a superclass includes a behavior the subclass does not support' do
209
+ behavior_info(:gen_foo, foo: 0)
210
+ superclass = Class.new{
211
+ behavior(:gen_foo)
212
+ }
213
+ subclass = Class.new(superclass)
214
+
215
+ lambda {
216
+ subclass.new
217
+ }.should raise_error(BehaviorError)
218
+ end
219
+
220
+ it 'raises an exception if a module includes a behavior the containing class does not support' do
221
+ behavior_info(:gen_foo, foo: 0)
222
+ mod = Module.new{
223
+ behavior(:gen_foo)
224
+ }
225
+ subclass = Class.new{
226
+ include mod
227
+ }
228
+
229
+ lambda {
230
+ subclass.new
231
+ }.should raise_error(BehaviorError)
232
+ end
233
+
234
+ it 'supports behaviors from multiple ancestors' do
235
+ behavior_info(:gen_foo, foo: 0)
236
+ behavior_info(:gen_bar, bar: 0)
237
+ behavior_info(:gen_baz, baz: 0)
238
+
239
+ rootclass = Class.new{ behavior(:gen_foo) }
240
+ superclass = Class.new(rootclass){ behavior(:gen_bar) }
241
+
242
+ subclass = Class.new(superclass){
243
+ behavior(:gen_baz)
244
+ def bar() nil; end
245
+ def baz() nil; end
246
+ }
247
+ lambda {
248
+ subclass.new
249
+ }.should raise_error(BehaviorError)
250
+
251
+ subclass = Class.new(superclass){
252
+ behavior(:gen_baz)
253
+ def foo() nil; end
254
+ def baz() nil; end
255
+ }
256
+ lambda {
257
+ subclass.new
258
+ }.should raise_error(BehaviorError)
259
+
260
+ subclass = Class.new(superclass){
261
+ behavior(:gen_baz)
262
+ def foo() nil; end
263
+ def bar() nil; end
264
+ }
265
+ lambda {
266
+ subclass.new
267
+ }.should raise_error(BehaviorError)
268
+
269
+ subclass = Class.new(superclass){
270
+ behavior(:gen_baz)
271
+ def foo() nil; end
272
+ def bar() nil; end
273
+ def baz() nil; end
274
+ }
275
+ lambda {
276
+ subclass.new
277
+ }.should_not raise_error
278
+ end
279
+
280
+ it 'supports multiple behaviors in an included module' do
281
+ behavior_info(:gen_foo, foo: 0)
282
+ behavior_info(:gen_bar, bar: 0)
283
+ behavior_info(:gen_baz, baz: 0)
284
+
285
+ mod = Module.new{
286
+ behavior(:gen_foo)
287
+ behavior(:gen_bar)
288
+ behavior(:gen_baz)
289
+ }
290
+
291
+ subclass = Class.new{
292
+ include mod
293
+ def bar() nil; end
294
+ def baz() nil; end
295
+ }
296
+ lambda {
297
+ subclass.new
298
+ }.should raise_error(BehaviorError)
299
+
300
+ subclass = Class.new{
301
+ include mod
302
+ def foo() nil; end
303
+ def baz() nil; end
304
+ }
305
+ lambda {
306
+ subclass.new
307
+ }.should raise_error(BehaviorError)
308
+
309
+ subclass = Class.new{
310
+ include mod
311
+ def foo() nil; end
312
+ def bar() nil; end
313
+ }
314
+ lambda {
315
+ subclass.new
316
+ }.should raise_error(BehaviorError)
317
+
318
+ subclass = Class.new{
319
+ include mod
320
+ def foo() nil; end
321
+ def bar() nil; end
322
+ def baz() nil; end
323
+ }
324
+ lambda {
325
+ subclass.new
326
+ }.should_not raise_error
327
+ end
328
+ end
329
+ end
330
+
331
+ context '#behaves_as?' do
332
+
333
+ it 'returns false when the behavior does not exist' do
334
+ clazz = Class.new { }
335
+ clazz.new.behaves_as?(:gen_foo).should be_false
336
+ end
337
+
338
+ it 'accepts behavior name as a symbol' do
339
+ behavior_info(:gen_foo)
340
+ clazz = Class.new { }
341
+ clazz.new.behaves_as?(:gen_foo).should be_true
342
+ end
343
+
344
+ it 'accepts behavior name as a string' do
345
+ behavior_info(:gen_foo)
346
+ clazz = Class.new { }
347
+ clazz.new.behaves_as?('gen_foo').should be_true
348
+ end
349
+
350
+ context 'Object' do
351
+
352
+ it 'returns true when the behavior is fully suported' do
353
+ behavior_info(:gen_foo, foo: 0, bar: 1, baz: 2)
354
+ clazz = Class.new {
355
+ def foo() nil; end
356
+ def bar(first) nil; end
357
+ def baz(first, second) nil; end
358
+ }
359
+
360
+ clazz.new.behaves_as?(:gen_foo).should be_true
361
+ end
362
+
363
+ it 'accepts any arity when function arity is set to :any' do
364
+ behavior_info(:gen_foo, foo: :any)
365
+ clazz = Class.new {
366
+ def foo(*args, &block) nil; end
367
+ }
368
+
369
+ clazz.new.behaves_as?(:gen_foo).should be_true
370
+ end
371
+
372
+ it 'returns false when the behavior is partially supported' do
373
+ behavior_info(:gen_foo, foo: 0, bar: 1, baz: 2)
374
+ clazz = Class.new {
375
+ def foo() nil; end
376
+ def bar(first) nil; end
377
+ }
378
+
379
+ clazz.new.behaves_as?(:gen_foo).should be_false
380
+ end
381
+
382
+ it 'returns false when the behavior is not supported at all' do
383
+ behavior_info(:gen_foo, foo: 0, bar: 1, baz: 2)
384
+ clazz = Class.new { }
385
+ clazz.new.behaves_as?(:gen_foo).should be_false
386
+ end
387
+
388
+ it 'raises an exception on failure when abend is true' do
389
+ behavior_info(:gen_foo, foo: 0)
390
+ behavior_info(:gen_bar, self_bar: 1)
391
+ behavior_info(:gen_baz, baz: :any)
392
+ clazz = Class.new { }
393
+
394
+ lambda {
395
+ clazz.new.behaves_as?(:gen_foo, true)
396
+ }.should raise_error(BehaviorError)
397
+
398
+ lambda {
399
+ clazz.new.behaves_as?(:gen_bar, true)
400
+ }.should raise_error(BehaviorError)
401
+
402
+ lambda {
403
+ clazz.new.behaves_as?(:gen_baz, true)
404
+ }.should raise_error(BehaviorError)
405
+ end
406
+
407
+ it 'exception includes the name and arity of the first missing function' do
408
+ behavior_info(:gen_foo, foo: 0)
409
+ behavior_info(:gen_bar, self_bar: 1)
410
+ behavior_info(:gen_baz, baz: :any)
411
+ clazz = Class.new { }
412
+
413
+ begin
414
+ clazz.new.behaves_as?(:gen_foo, true)
415
+ rescue BehaviorError => ex
416
+ ex.message.should =~ /foo\/0/
417
+ end
418
+
419
+ begin
420
+ clazz.new.behaves_as?(:gen_bar, true)
421
+ rescue BehaviorError => ex
422
+ ex.message.should =~ /#self\.bar\/1/
423
+ end
424
+
425
+ begin
426
+ clazz.new.behaves_as?(:gen_baz, true)
427
+ rescue BehaviorError => ex
428
+ ex.message.should =~ /#baz\/:any/
429
+ end
430
+ end
431
+ end
432
+
433
+ context 'Class' do
434
+
435
+ it 'returns true when the behavior is fully suported' do
436
+ behavior_info(:gen_foo, self_foo: 0, self_bar: 1, baz: 2)
437
+ clazz = Class.new {
438
+ def self.foo() nil; end
439
+ def self.bar(first) nil; end
440
+ def baz(first, second) nil; end
441
+ }
442
+
443
+ clazz.behaves_as?(:gen_foo).should be_true
444
+ clazz.new.behaves_as?(:gen_foo).should be_true
445
+ end
446
+
447
+ it 'accepts any arity when function arity is set to :any' do
448
+ behavior_info(:gen_foo, self_foo: :any)
449
+ clazz = Class.new {
450
+ def self.foo(*args, &block) nil; end
451
+ }
452
+
453
+ clazz.behaves_as?(:gen_foo).should be_true
454
+ clazz.new.behaves_as?(:gen_foo).should be_true
455
+ end
456
+
457
+ it 'returns false when the behavior is partially supported' do
458
+ behavior_info(:gen_foo, self_foo: 0, bar: 1, self_baz: 2)
459
+ clazz = Class.new {
460
+ def self.foo() nil; end
461
+ def self(first) nil; end
462
+ }
463
+
464
+ clazz.behaves_as?(:gen_foo).should be_false
465
+ clazz.new.behaves_as?(:gen_foo).should be_false
466
+ end
467
+
468
+ it 'returns false when the behavior is not supported at all' do
469
+ behavior_info(:gen_foo, self_foo: 0, self_bar: 1, self_baz: 2)
470
+ clazz = Class.new { }
471
+ clazz.new.behaves_as?(:gen_foo).should be_false
472
+ end
473
+ end
474
+ end
475
+
476
+ context 'aliases' do
477
+
478
+ it 'aliases behaviour_info for behavior_info' do
479
+ behaviour_info(:gen_foo)
480
+ clazz = Class.new { }
481
+ clazz.new.behaves_as?(:gen_foo).should be_true
482
+ end
483
+
484
+ it 'aliases interface for behavior_info' do
485
+ interface(:gen_foo)
486
+ clazz = Class.new { }
487
+ clazz.new.behaves_as?(:gen_foo).should be_true
488
+ end
489
+
490
+ it 'aliases behaviour for behavior' do
491
+ behavior_info(:gen_foo, foo: 0)
492
+ clazz = Class.new {
493
+ behaviour(:gen_foo)
494
+ def foo() nil; end
495
+ }
496
+ clazz.new.behaves_as?(:gen_foo).should be_true
497
+ end
498
+
499
+ it 'aliases behaves_as for behavior' do
500
+ behavior_info(:gen_foo, foo: 0)
501
+ clazz = Class.new {
502
+ behaves_as :gen_foo
503
+ def foo() nil; end
504
+ }
505
+ clazz.new.behaves_as?(:gen_foo).should be_true
506
+ end
507
+ end
508
+ end