functional-ruby 0.7.1 → 0.7.2

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/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,369 +1,464 @@
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
- end
234
- end
235
-
236
- context '#behaves_as?' do
237
-
238
- it 'returns false when the behavior does not exist' do
239
- clazz = Class.new { }
240
- clazz.new.behaves_as?(:gen_foo).should be_false
241
- end
242
-
243
- it 'accepts behavior name as a symbol' do
244
- behavior_info(:gen_foo)
245
- clazz = Class.new { }
246
- clazz.new.behaves_as?(:gen_foo).should be_true
247
- end
248
-
249
- it 'accepts behavior name as a string' do
250
- behavior_info(:gen_foo)
251
- clazz = Class.new { }
252
- clazz.new.behaves_as?('gen_foo').should be_true
253
- end
254
-
255
- context 'Object' do
256
-
257
- it 'returns true when the behavior is fully suported' do
258
- behavior_info(:gen_foo, foo: 0, bar: 1, baz: 2)
259
- clazz = Class.new {
260
- def foo() nil; end
261
- def bar(first) nil; end
262
- def baz(first, second) nil; end
263
- }
264
-
265
- clazz.new.behaves_as?(:gen_foo).should be_true
266
- end
267
-
268
- it 'accepts any arity when function arity is set to :any' do
269
- behavior_info(:gen_foo, foo: :any)
270
- clazz = Class.new {
271
- def foo(*args, &block) nil; end
272
- }
273
-
274
- clazz.new.behaves_as?(:gen_foo).should be_true
275
- end
276
-
277
- it 'returns false when the behavior is partially supported' do
278
- behavior_info(:gen_foo, foo: 0, bar: 1, baz: 2)
279
- clazz = Class.new {
280
- def foo() nil; end
281
- def bar(first) nil; end
282
- }
283
-
284
- clazz.new.behaves_as?(:gen_foo).should be_false
285
- end
286
-
287
- it 'returns false when the behavior is not supported at all' do
288
- behavior_info(:gen_foo, foo: 0, bar: 1, baz: 2)
289
- clazz = Class.new { }
290
- clazz.new.behaves_as?(:gen_foo).should be_false
291
- end
292
- end
293
-
294
- context 'Class' do
295
-
296
- it 'returns true when the behavior is fully suported' do
297
- behavior_info(:gen_foo, self_foo: 0, self_bar: 1, baz: 2)
298
- clazz = Class.new {
299
- def self.foo() nil; end
300
- def self.bar(first) nil; end
301
- def baz(first, second) nil; end
302
- }
303
-
304
- clazz.behaves_as?(:gen_foo).should be_true
305
- clazz.new.behaves_as?(:gen_foo).should be_true
306
- end
307
-
308
- it 'accepts any arity when function arity is set to :any' do
309
- behavior_info(:gen_foo, self_foo: :any)
310
- clazz = Class.new {
311
- def self.foo(*args, &block) nil; end
312
- }
313
-
314
- clazz.behaves_as?(:gen_foo).should be_true
315
- clazz.new.behaves_as?(:gen_foo).should be_true
316
- end
317
-
318
- it 'returns false when the behavior is partially supported' do
319
- behavior_info(:gen_foo, self_foo: 0, bar: 1, self_baz: 2)
320
- clazz = Class.new {
321
- def self.foo() nil; end
322
- def self(first) nil; end
323
- }
324
-
325
- clazz.behaves_as?(:gen_foo).should be_false
326
- clazz.new.behaves_as?(:gen_foo).should be_false
327
- end
328
-
329
- it 'returns false when the behavior is not supported at all' do
330
- behavior_info(:gen_foo, self_foo: 0, self_bar: 1, self_baz: 2)
331
- clazz = Class.new { }
332
- clazz.new.behaves_as?(:gen_foo).should be_false
333
- end
334
- end
335
- end
336
-
337
- context 'aliases' do
338
-
339
- it 'aliases behaviour_info for behavior_info' do
340
- behaviour_info(:gen_foo)
341
- clazz = Class.new { }
342
- clazz.new.behaves_as?(:gen_foo).should be_true
343
- end
344
-
345
- it 'aliases interface for behavior_info' do
346
- interface(:gen_foo)
347
- clazz = Class.new { }
348
- clazz.new.behaves_as?(:gen_foo).should be_true
349
- end
350
-
351
- it 'aliases behaviour for behavior' do
352
- behavior_info(:gen_foo, foo: 0)
353
- clazz = Class.new {
354
- behaviour(:gen_foo)
355
- def foo() nil; end
356
- }
357
- clazz.new.behaves_as?(:gen_foo).should be_true
358
- end
359
-
360
- it 'aliases behaves_as for behavior' do
361
- behavior_info(:gen_foo, foo: 0)
362
- clazz = Class.new {
363
- behaves_as :gen_foo
364
- def foo() nil; end
365
- }
366
- clazz.new.behaves_as?(:gen_foo).should be_true
367
- end
368
- end
369
- 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
+ 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