functional-ruby 0.7.7 → 1.0.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.
- checksums.yaml +4 -4
- data/README.md +92 -152
- data/doc/memo.txt +192 -0
- data/doc/pattern_matching.txt +485 -0
- data/doc/protocol.txt +221 -0
- data/doc/record.txt +144 -0
- data/doc/thread_safety.txt +8 -0
- data/lib/functional.rb +48 -18
- data/lib/functional/abstract_struct.rb +161 -0
- data/lib/functional/delay.rb +117 -0
- data/lib/functional/either.rb +222 -0
- data/lib/functional/memo.rb +93 -0
- data/lib/functional/method_signature.rb +72 -0
- data/lib/functional/option.rb +209 -0
- data/lib/functional/pattern_matching.rb +117 -100
- data/lib/functional/protocol.rb +157 -0
- data/lib/functional/protocol_info.rb +193 -0
- data/lib/functional/record.rb +155 -0
- data/lib/functional/type_check.rb +112 -0
- data/lib/functional/union.rb +152 -0
- data/lib/functional/version.rb +3 -1
- data/spec/functional/abstract_struct_shared.rb +154 -0
- data/spec/functional/complex_pattern_matching_spec.rb +205 -0
- data/spec/functional/configuration_spec.rb +17 -0
- data/spec/functional/delay_spec.rb +147 -0
- data/spec/functional/either_spec.rb +237 -0
- data/spec/functional/memo_spec.rb +207 -0
- data/spec/functional/option_spec.rb +292 -0
- data/spec/functional/pattern_matching_spec.rb +279 -276
- data/spec/functional/protocol_info_spec.rb +444 -0
- data/spec/functional/protocol_spec.rb +274 -0
- data/spec/functional/record_spec.rb +175 -0
- data/spec/functional/type_check_spec.rb +103 -0
- data/spec/functional/union_spec.rb +110 -0
- data/spec/spec_helper.rb +6 -4
- metadata +55 -45
- data/lib/functional/behavior.rb +0 -138
- data/lib/functional/behaviour.rb +0 -2
- data/lib/functional/catalog.rb +0 -487
- data/lib/functional/collection.rb +0 -403
- data/lib/functional/inflect.rb +0 -127
- data/lib/functional/platform.rb +0 -120
- data/lib/functional/search.rb +0 -132
- data/lib/functional/sort.rb +0 -41
- data/lib/functional/utilities.rb +0 -189
- data/md/behavior.md +0 -188
- data/md/catalog.md +0 -32
- data/md/collection.md +0 -32
- data/md/inflect.md +0 -32
- data/md/pattern_matching.md +0 -512
- data/md/platform.md +0 -32
- data/md/search.md +0 -32
- data/md/sort.md +0 -32
- data/md/utilities.md +0 -55
- data/spec/functional/behavior_spec.rb +0 -528
- data/spec/functional/catalog_spec.rb +0 -1206
- data/spec/functional/collection_spec.rb +0 -752
- data/spec/functional/inflect_spec.rb +0 -85
- data/spec/functional/integration_spec.rb +0 -205
- data/spec/functional/platform_spec.rb +0 -501
- data/spec/functional/search_spec.rb +0 -187
- data/spec/functional/sort_spec.rb +0 -61
- data/spec/functional/utilities_spec.rb +0 -277
data/md/platform.md
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
# Platform
|
2
|
-
|
3
|
-
TBD...
|
4
|
-
|
5
|
-
## Copyright
|
6
|
-
|
7
|
-
*Functional Ruby* is Copyright © 2013 [Jerry D'Antonio](https://twitter.com/jerrydantonio).
|
8
|
-
It is free software and may be redistributed under the terms specified in the LICENSE file.
|
9
|
-
|
10
|
-
## License
|
11
|
-
|
12
|
-
Released under the MIT license.
|
13
|
-
|
14
|
-
http://www.opensource.org/licenses/mit-license.php
|
15
|
-
|
16
|
-
> Permission is hereby granted, free of charge, to any person obtaining a copy
|
17
|
-
> of this software and associated documentation files (the "Software"), to deal
|
18
|
-
> in the Software without restriction, including without limitation the rights
|
19
|
-
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
20
|
-
> copies of the Software, and to permit persons to whom the Software is
|
21
|
-
> furnished to do so, subject to the following conditions:
|
22
|
-
>
|
23
|
-
> The above copyright notice and this permission notice shall be included in
|
24
|
-
> all copies or substantial portions of the Software.
|
25
|
-
>
|
26
|
-
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
27
|
-
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
28
|
-
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
29
|
-
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
30
|
-
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
31
|
-
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
32
|
-
> THE SOFTWARE.
|
data/md/search.md
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
# Search
|
2
|
-
|
3
|
-
TBD...
|
4
|
-
|
5
|
-
## Copyright
|
6
|
-
|
7
|
-
*Functional Ruby* is Copyright © 2013 [Jerry D'Antonio](https://twitter.com/jerrydantonio).
|
8
|
-
It is free software and may be redistributed under the terms specified in the LICENSE file.
|
9
|
-
|
10
|
-
## License
|
11
|
-
|
12
|
-
Released under the MIT license.
|
13
|
-
|
14
|
-
http://www.opensource.org/licenses/mit-license.php
|
15
|
-
|
16
|
-
> Permission is hereby granted, free of charge, to any person obtaining a copy
|
17
|
-
> of this software and associated documentation files (the "Software"), to deal
|
18
|
-
> in the Software without restriction, including without limitation the rights
|
19
|
-
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
20
|
-
> copies of the Software, and to permit persons to whom the Software is
|
21
|
-
> furnished to do so, subject to the following conditions:
|
22
|
-
>
|
23
|
-
> The above copyright notice and this permission notice shall be included in
|
24
|
-
> all copies or substantial portions of the Software.
|
25
|
-
>
|
26
|
-
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
27
|
-
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
28
|
-
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
29
|
-
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
30
|
-
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
31
|
-
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
32
|
-
> THE SOFTWARE.
|
data/md/sort.md
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
# Sort
|
2
|
-
|
3
|
-
TBD...
|
4
|
-
|
5
|
-
## Copyright
|
6
|
-
|
7
|
-
*Functional Ruby* is Copyright © 2013 [Jerry D'Antonio](https://twitter.com/jerrydantonio).
|
8
|
-
It is free software and may be redistributed under the terms specified in the LICENSE file.
|
9
|
-
|
10
|
-
## License
|
11
|
-
|
12
|
-
Released under the MIT license.
|
13
|
-
|
14
|
-
http://www.opensource.org/licenses/mit-license.php
|
15
|
-
|
16
|
-
> Permission is hereby granted, free of charge, to any person obtaining a copy
|
17
|
-
> of this software and associated documentation files (the "Software"), to deal
|
18
|
-
> in the Software without restriction, including without limitation the rights
|
19
|
-
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
20
|
-
> copies of the Software, and to permit persons to whom the Software is
|
21
|
-
> furnished to do so, subject to the following conditions:
|
22
|
-
>
|
23
|
-
> The above copyright notice and this permission notice shall be included in
|
24
|
-
> all copies or substantial portions of the Software.
|
25
|
-
>
|
26
|
-
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
27
|
-
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
28
|
-
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
29
|
-
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
30
|
-
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
31
|
-
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
32
|
-
> THE SOFTWARE.
|
data/md/utilities.md
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
# Utility Functions
|
2
|
-
|
3
|
-
Start by requiring the Functional Ruby gem:
|
4
|
-
|
5
|
-
```ruby
|
6
|
-
require 'functional'
|
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,528 +0,0 @@
|
|
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
|
-
it 'allows constructor check to be permanently disabled when gem loaded' do
|
103
|
-
|
104
|
-
@original_config = $ENABLE_BEHAVIOR_CHECK_ON_CONSTRUCTION
|
105
|
-
|
106
|
-
behavior_info(:gen_foo, foo: 0)
|
107
|
-
|
108
|
-
$ENABLE_BEHAVIOR_CHECK_ON_CONSTRUCTION = true
|
109
|
-
load(File.join(File.dirname(__FILE__), '../../', 'lib/functional/behavior.rb'))
|
110
|
-
clazz = Class.new { behavior(:gen_foo) }
|
111
|
-
expect { clazz.new }.to raise_error(BehaviorError)
|
112
|
-
|
113
|
-
$ENABLE_BEHAVIOR_CHECK_ON_CONSTRUCTION = false
|
114
|
-
load(File.join(File.dirname(__FILE__), '../../', 'lib/functional/behavior.rb'))
|
115
|
-
clazz = Class.new { behavior(:gen_foo) }
|
116
|
-
expect { clazz.new }.not_to raise_error()
|
117
|
-
|
118
|
-
$ENABLE_BEHAVIOR_CHECK_ON_CONSTRUCTION = @original_config
|
119
|
-
load(File.join(File.dirname(__FILE__), '../../', 'lib/functional/behavior.rb'))
|
120
|
-
end
|
121
|
-
|
122
|
-
context 'instance methods' do
|
123
|
-
|
124
|
-
it 'raises an exception when one or more function definitions are missing' do
|
125
|
-
behavior_info(:gen_foo, foo: 0, bar: 1)
|
126
|
-
clazz = Class.new {
|
127
|
-
behavior(:gen_foo)
|
128
|
-
def foo() nil; end
|
129
|
-
}
|
130
|
-
|
131
|
-
lambda {
|
132
|
-
clazz.new
|
133
|
-
}.should raise_error(BehaviorError)
|
134
|
-
end
|
135
|
-
|
136
|
-
it 'raises an exception when one or more functions do not have proper arity' do
|
137
|
-
behavior_info(:gen_foo, foo: 0)
|
138
|
-
clazz = Class.new {
|
139
|
-
behavior(:gen_foo)
|
140
|
-
def foo(broken) nil; end
|
141
|
-
}
|
142
|
-
|
143
|
-
lambda {
|
144
|
-
clazz.new
|
145
|
-
}.should raise_error(BehaviorError)
|
146
|
-
end
|
147
|
-
|
148
|
-
it 'accepts any arity when function arity is set to :any' do
|
149
|
-
behavior_info(:gen_foo, foo: :any)
|
150
|
-
clazz = Class.new {
|
151
|
-
behavior(:gen_foo)
|
152
|
-
def foo(first) nil; end
|
153
|
-
}
|
154
|
-
|
155
|
-
lambda {
|
156
|
-
clazz.new
|
157
|
-
}.should_not raise_error
|
158
|
-
end
|
159
|
-
|
160
|
-
it 'creates the object when function definitions match' do
|
161
|
-
behavior_info(:gen_foo, foo: 0, bar: 1)
|
162
|
-
clazz = Class.new {
|
163
|
-
behavior(:gen_foo)
|
164
|
-
def foo() nil; end
|
165
|
-
def bar(first) nil; end
|
166
|
-
}
|
167
|
-
|
168
|
-
lambda {
|
169
|
-
clazz.new
|
170
|
-
}.should_not raise_error
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
context 'class methods' do
|
175
|
-
|
176
|
-
it 'raises an exception when one or more function definitions are missing' do
|
177
|
-
behavior_info(:gen_foo, self_foo: 0, self_bar: 1)
|
178
|
-
clazz = Class.new {
|
179
|
-
behavior(:gen_foo)
|
180
|
-
def self.foo() nil; end
|
181
|
-
}
|
182
|
-
|
183
|
-
lambda {
|
184
|
-
clazz.new
|
185
|
-
}.should raise_error(BehaviorError)
|
186
|
-
end
|
187
|
-
|
188
|
-
it 'raises an exception when one or more functions do not have proper arity' do
|
189
|
-
behavior_info(:gen_foo, self_foo: 0)
|
190
|
-
clazz = Class.new {
|
191
|
-
behavior(:gen_foo)
|
192
|
-
def self.foo(broken) nil; end
|
193
|
-
}
|
194
|
-
|
195
|
-
lambda {
|
196
|
-
clazz.new
|
197
|
-
}.should raise_error(BehaviorError)
|
198
|
-
end
|
199
|
-
|
200
|
-
it 'accepts any arity when function arity is set to :any' do
|
201
|
-
behavior_info(:gen_foo, self_foo: :any)
|
202
|
-
clazz = Class.new {
|
203
|
-
behavior(:gen_foo)
|
204
|
-
def self.foo(first) nil; end
|
205
|
-
}
|
206
|
-
|
207
|
-
lambda {
|
208
|
-
clazz.new
|
209
|
-
}.should_not raise_error
|
210
|
-
end
|
211
|
-
|
212
|
-
it 'creates the object when function definitions match' do
|
213
|
-
behavior_info(:gen_foo, self_foo: 0, self_bar: 1)
|
214
|
-
clazz = Class.new {
|
215
|
-
behavior(:gen_foo)
|
216
|
-
def self.foo() nil; end
|
217
|
-
def self.bar(first) nil; end
|
218
|
-
}
|
219
|
-
|
220
|
-
lambda {
|
221
|
-
clazz.new
|
222
|
-
}.should_not raise_error
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
context 'inheritance' do
|
227
|
-
|
228
|
-
it 'raises an exception if a superclass includes a behavior the subclass does not support' do
|
229
|
-
behavior_info(:gen_foo, foo: 0)
|
230
|
-
superclass = Class.new{
|
231
|
-
behavior(:gen_foo)
|
232
|
-
}
|
233
|
-
subclass = Class.new(superclass)
|
234
|
-
|
235
|
-
lambda {
|
236
|
-
subclass.new
|
237
|
-
}.should raise_error(BehaviorError)
|
238
|
-
end
|
239
|
-
|
240
|
-
it 'raises an exception if a module includes a behavior the containing class does not support' do
|
241
|
-
behavior_info(:gen_foo, foo: 0)
|
242
|
-
mod = Module.new{
|
243
|
-
behavior(:gen_foo)
|
244
|
-
}
|
245
|
-
subclass = Class.new{
|
246
|
-
include mod
|
247
|
-
}
|
248
|
-
|
249
|
-
lambda {
|
250
|
-
subclass.new
|
251
|
-
}.should raise_error(BehaviorError)
|
252
|
-
end
|
253
|
-
|
254
|
-
it 'supports behaviors from multiple ancestors' do
|
255
|
-
behavior_info(:gen_foo, foo: 0)
|
256
|
-
behavior_info(:gen_bar, bar: 0)
|
257
|
-
behavior_info(:gen_baz, baz: 0)
|
258
|
-
|
259
|
-
rootclass = Class.new{ behavior(:gen_foo) }
|
260
|
-
superclass = Class.new(rootclass){ behavior(:gen_bar) }
|
261
|
-
|
262
|
-
subclass = Class.new(superclass){
|
263
|
-
behavior(:gen_baz)
|
264
|
-
def bar() nil; end
|
265
|
-
def baz() nil; end
|
266
|
-
}
|
267
|
-
lambda {
|
268
|
-
subclass.new
|
269
|
-
}.should raise_error(BehaviorError)
|
270
|
-
|
271
|
-
subclass = Class.new(superclass){
|
272
|
-
behavior(:gen_baz)
|
273
|
-
def foo() nil; end
|
274
|
-
def baz() nil; end
|
275
|
-
}
|
276
|
-
lambda {
|
277
|
-
subclass.new
|
278
|
-
}.should raise_error(BehaviorError)
|
279
|
-
|
280
|
-
subclass = Class.new(superclass){
|
281
|
-
behavior(:gen_baz)
|
282
|
-
def foo() nil; end
|
283
|
-
def bar() nil; end
|
284
|
-
}
|
285
|
-
lambda {
|
286
|
-
subclass.new
|
287
|
-
}.should raise_error(BehaviorError)
|
288
|
-
|
289
|
-
subclass = Class.new(superclass){
|
290
|
-
behavior(:gen_baz)
|
291
|
-
def foo() nil; end
|
292
|
-
def bar() nil; end
|
293
|
-
def baz() nil; end
|
294
|
-
}
|
295
|
-
lambda {
|
296
|
-
subclass.new
|
297
|
-
}.should_not raise_error
|
298
|
-
end
|
299
|
-
|
300
|
-
it 'supports multiple behaviors in an included module' do
|
301
|
-
behavior_info(:gen_foo, foo: 0)
|
302
|
-
behavior_info(:gen_bar, bar: 0)
|
303
|
-
behavior_info(:gen_baz, baz: 0)
|
304
|
-
|
305
|
-
mod = Module.new{
|
306
|
-
behavior(:gen_foo)
|
307
|
-
behavior(:gen_bar)
|
308
|
-
behavior(:gen_baz)
|
309
|
-
}
|
310
|
-
|
311
|
-
subclass = Class.new{
|
312
|
-
include mod
|
313
|
-
def bar() nil; end
|
314
|
-
def baz() nil; end
|
315
|
-
}
|
316
|
-
lambda {
|
317
|
-
subclass.new
|
318
|
-
}.should raise_error(BehaviorError)
|
319
|
-
|
320
|
-
subclass = Class.new{
|
321
|
-
include mod
|
322
|
-
def foo() nil; end
|
323
|
-
def baz() nil; end
|
324
|
-
}
|
325
|
-
lambda {
|
326
|
-
subclass.new
|
327
|
-
}.should raise_error(BehaviorError)
|
328
|
-
|
329
|
-
subclass = Class.new{
|
330
|
-
include mod
|
331
|
-
def foo() nil; end
|
332
|
-
def bar() nil; end
|
333
|
-
}
|
334
|
-
lambda {
|
335
|
-
subclass.new
|
336
|
-
}.should raise_error(BehaviorError)
|
337
|
-
|
338
|
-
subclass = Class.new{
|
339
|
-
include mod
|
340
|
-
def foo() nil; end
|
341
|
-
def bar() nil; end
|
342
|
-
def baz() nil; end
|
343
|
-
}
|
344
|
-
lambda {
|
345
|
-
subclass.new
|
346
|
-
}.should_not raise_error
|
347
|
-
end
|
348
|
-
end
|
349
|
-
end
|
350
|
-
|
351
|
-
context '#behaves_as?' do
|
352
|
-
|
353
|
-
it 'returns false when the behavior does not exist' do
|
354
|
-
clazz = Class.new { }
|
355
|
-
clazz.new.behaves_as?(:gen_foo).should be_false
|
356
|
-
end
|
357
|
-
|
358
|
-
it 'accepts behavior name as a symbol' do
|
359
|
-
behavior_info(:gen_foo)
|
360
|
-
clazz = Class.new { }
|
361
|
-
clazz.new.behaves_as?(:gen_foo).should be_true
|
362
|
-
end
|
363
|
-
|
364
|
-
it 'accepts behavior name as a string' do
|
365
|
-
behavior_info(:gen_foo)
|
366
|
-
clazz = Class.new { }
|
367
|
-
clazz.new.behaves_as?('gen_foo').should be_true
|
368
|
-
end
|
369
|
-
|
370
|
-
context 'Object' do
|
371
|
-
|
372
|
-
it 'returns true when the behavior is fully suported' 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
|
-
def baz(first, second) nil; end
|
378
|
-
}
|
379
|
-
|
380
|
-
clazz.new.behaves_as?(:gen_foo).should be_true
|
381
|
-
end
|
382
|
-
|
383
|
-
it 'accepts any arity when function arity is set to :any' do
|
384
|
-
behavior_info(:gen_foo, foo: :any)
|
385
|
-
clazz = Class.new {
|
386
|
-
def foo(*args, &block) nil; end
|
387
|
-
}
|
388
|
-
|
389
|
-
clazz.new.behaves_as?(:gen_foo).should be_true
|
390
|
-
end
|
391
|
-
|
392
|
-
it 'returns false when the behavior is partially supported' do
|
393
|
-
behavior_info(:gen_foo, foo: 0, bar: 1, baz: 2)
|
394
|
-
clazz = Class.new {
|
395
|
-
def foo() nil; end
|
396
|
-
def bar(first) nil; end
|
397
|
-
}
|
398
|
-
|
399
|
-
clazz.new.behaves_as?(:gen_foo).should be_false
|
400
|
-
end
|
401
|
-
|
402
|
-
it 'returns false when the behavior is not supported at all' do
|
403
|
-
behavior_info(:gen_foo, foo: 0, bar: 1, baz: 2)
|
404
|
-
clazz = Class.new { }
|
405
|
-
clazz.new.behaves_as?(:gen_foo).should be_false
|
406
|
-
end
|
407
|
-
|
408
|
-
it 'raises an exception on failure when abend is true' do
|
409
|
-
behavior_info(:gen_foo, foo: 0)
|
410
|
-
behavior_info(:gen_bar, self_bar: 1)
|
411
|
-
behavior_info(:gen_baz, baz: :any)
|
412
|
-
clazz = Class.new { }
|
413
|
-
|
414
|
-
lambda {
|
415
|
-
clazz.new.behaves_as?(:gen_foo, true)
|
416
|
-
}.should raise_error(BehaviorError)
|
417
|
-
|
418
|
-
lambda {
|
419
|
-
clazz.new.behaves_as?(:gen_bar, true)
|
420
|
-
}.should raise_error(BehaviorError)
|
421
|
-
|
422
|
-
lambda {
|
423
|
-
clazz.new.behaves_as?(:gen_baz, true)
|
424
|
-
}.should raise_error(BehaviorError)
|
425
|
-
end
|
426
|
-
|
427
|
-
it 'exception includes the name and arity of the first missing function' do
|
428
|
-
behavior_info(:gen_foo, foo: 0)
|
429
|
-
behavior_info(:gen_bar, self_bar: 1)
|
430
|
-
behavior_info(:gen_baz, baz: :any)
|
431
|
-
clazz = Class.new { }
|
432
|
-
|
433
|
-
begin
|
434
|
-
clazz.new.behaves_as?(:gen_foo, true)
|
435
|
-
rescue BehaviorError => ex
|
436
|
-
ex.message.should =~ /foo\/0/
|
437
|
-
end
|
438
|
-
|
439
|
-
begin
|
440
|
-
clazz.new.behaves_as?(:gen_bar, true)
|
441
|
-
rescue BehaviorError => ex
|
442
|
-
ex.message.should =~ /#self\.bar\/1/
|
443
|
-
end
|
444
|
-
|
445
|
-
begin
|
446
|
-
clazz.new.behaves_as?(:gen_baz, true)
|
447
|
-
rescue BehaviorError => ex
|
448
|
-
ex.message.should =~ /#baz\/:any/
|
449
|
-
end
|
450
|
-
end
|
451
|
-
end
|
452
|
-
|
453
|
-
context 'Class' do
|
454
|
-
|
455
|
-
it 'returns true when the behavior is fully suported' do
|
456
|
-
behavior_info(:gen_foo, self_foo: 0, self_bar: 1, baz: 2)
|
457
|
-
clazz = Class.new {
|
458
|
-
def self.foo() nil; end
|
459
|
-
def self.bar(first) nil; end
|
460
|
-
def baz(first, second) nil; end
|
461
|
-
}
|
462
|
-
|
463
|
-
clazz.behaves_as?(:gen_foo).should be_true
|
464
|
-
clazz.new.behaves_as?(:gen_foo).should be_true
|
465
|
-
end
|
466
|
-
|
467
|
-
it 'accepts any arity when function arity is set to :any' do
|
468
|
-
behavior_info(:gen_foo, self_foo: :any)
|
469
|
-
clazz = Class.new {
|
470
|
-
def self.foo(*args, &block) nil; end
|
471
|
-
}
|
472
|
-
|
473
|
-
clazz.behaves_as?(:gen_foo).should be_true
|
474
|
-
clazz.new.behaves_as?(:gen_foo).should be_true
|
475
|
-
end
|
476
|
-
|
477
|
-
it 'returns false when the behavior is partially supported' do
|
478
|
-
behavior_info(:gen_foo, self_foo: 0, bar: 1, self_baz: 2)
|
479
|
-
clazz = Class.new {
|
480
|
-
def self.foo() nil; end
|
481
|
-
def self(first) nil; end
|
482
|
-
}
|
483
|
-
|
484
|
-
clazz.behaves_as?(:gen_foo).should be_false
|
485
|
-
clazz.new.behaves_as?(:gen_foo).should be_false
|
486
|
-
end
|
487
|
-
|
488
|
-
it 'returns false when the behavior is not supported at all' do
|
489
|
-
behavior_info(:gen_foo, self_foo: 0, self_bar: 1, self_baz: 2)
|
490
|
-
clazz = Class.new { }
|
491
|
-
clazz.new.behaves_as?(:gen_foo).should be_false
|
492
|
-
end
|
493
|
-
end
|
494
|
-
end
|
495
|
-
|
496
|
-
context 'aliases' do
|
497
|
-
|
498
|
-
it 'aliases behaviour_info for behavior_info' do
|
499
|
-
behaviour_info(:gen_foo)
|
500
|
-
clazz = Class.new { }
|
501
|
-
clazz.new.behaves_as?(:gen_foo).should be_true
|
502
|
-
end
|
503
|
-
|
504
|
-
it 'aliases interface for behavior_info' do
|
505
|
-
interface(:gen_foo)
|
506
|
-
clazz = Class.new { }
|
507
|
-
clazz.new.behaves_as?(:gen_foo).should be_true
|
508
|
-
end
|
509
|
-
|
510
|
-
it 'aliases behaviour for behavior' do
|
511
|
-
behavior_info(:gen_foo, foo: 0)
|
512
|
-
clazz = Class.new {
|
513
|
-
behaviour(:gen_foo)
|
514
|
-
def foo() nil; end
|
515
|
-
}
|
516
|
-
clazz.new.behaves_as?(:gen_foo).should be_true
|
517
|
-
end
|
518
|
-
|
519
|
-
it 'aliases behaves_as for behavior' do
|
520
|
-
behavior_info(:gen_foo, foo: 0)
|
521
|
-
clazz = Class.new {
|
522
|
-
behaves_as :gen_foo
|
523
|
-
def foo() nil; end
|
524
|
-
}
|
525
|
-
clazz.new.behaves_as?(:gen_foo).should be_true
|
526
|
-
end
|
527
|
-
end
|
528
|
-
end
|