ruleby 0.9.b4 → 0.9.b7
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/.gitignore +5 -0
- data/GPL.txt +341 -0
- data/LICENSE.txt +52 -0
- data/README.markdown +22 -0
- data/benchmarks/basic_rules.rb +61 -0
- data/benchmarks/joined_rules.rb +66 -0
- data/benchmarks/miss_manners/data.rb +146 -0
- data/benchmarks/miss_manners/miss_manners.rb +33 -0
- data/benchmarks/miss_manners/model.rb +193 -0
- data/benchmarks/miss_manners/rules.rb +105 -0
- data/benchmarks/model.rb +36 -0
- data/examples/diagnosis.rb +129 -0
- data/examples/fibonacci_example1.rb +44 -0
- data/examples/fibonacci_example2.rb +40 -0
- data/examples/fibonacci_example3.rb +78 -0
- data/examples/fibonacci_rulebook.rb +84 -0
- data/examples/hello.rb +45 -0
- data/examples/ticket.rb +113 -0
- data/examples/wordgame.rb +107 -0
- data/lib/core/engine.rb +26 -24
- data/lib/core/nodes.rb +77 -35
- data/lib/ruleby.rb +0 -37
- data/ruleby.gemspec +17 -0
- data/spec/and_or_spec.rb +252 -0
- data/spec/coercion_spec.rb +5 -0
- data/spec/collect_spec.rb +1021 -0
- data/spec/errors_spec.rb +148 -0
- data/spec/ferrari_spec.rb +39 -0
- data/spec/function_spec.rb +199 -0
- data/spec/hello_spec.rb +34 -0
- data/spec/node_sharing_spec.rb +53 -0
- data/spec/property_spec.rb +69 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +9 -0
- data/tasks/documentation.rake +32 -0
- data/tasks/rspec.rake +21 -0
- data/tasks/test.rake +9 -0
- data/tests/assert_facts.rb +130 -0
- data/tests/common.rb +29 -0
- data/tests/duck_type.rb +79 -0
- data/tests/gets.rb +48 -0
- data/tests/join_nodes.rb +63 -0
- data/tests/nil.rb +72 -0
- data/tests/not_patterns.rb +91 -0
- data/tests/or_patterns.rb +154 -0
- data/tests/regex.rb +47 -0
- data/tests/self_reference.rb +54 -0
- metadata +81 -49
data/lib/ruleby.rb
CHANGED
|
@@ -19,41 +19,4 @@ module Ruleby
|
|
|
19
19
|
yield e if block_given?
|
|
20
20
|
return e
|
|
21
21
|
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
class String
|
|
25
|
-
unless ''.respond_to?(:to_proc)
|
|
26
|
-
def to_proc &block
|
|
27
|
-
params = []
|
|
28
|
-
expr = self
|
|
29
|
-
sections = expr.split(/\s*->\s*/m)
|
|
30
|
-
if sections.length > 1 then
|
|
31
|
-
eval sections.reverse!.inject { |e, p| "(Proc.new { |#{p.split(/\s/).join(', ')}| #{e} })" }, block && block.binding
|
|
32
|
-
elsif expr.match(/\b_\b/)
|
|
33
|
-
eval "Proc.new { |_| #{expr} }", block && block.binding
|
|
34
|
-
else
|
|
35
|
-
leftSection = expr.match(/^\s*(?:[+*\/%&|\^\.=<>\[]|!=)/m)
|
|
36
|
-
rightSection = expr.match(/[+\-*\/%&|\^\.=<>!]\s*$/m)
|
|
37
|
-
if leftSection || rightSection then
|
|
38
|
-
if (leftSection) then
|
|
39
|
-
params.push('$left')
|
|
40
|
-
expr = '$left' + expr
|
|
41
|
-
end
|
|
42
|
-
if (rightSection) then
|
|
43
|
-
params.push('$right')
|
|
44
|
-
expr = expr + '$right'
|
|
45
|
-
end
|
|
46
|
-
else
|
|
47
|
-
self.gsub(
|
|
48
|
-
/(?:\b[A-Z]|\.[a-zA-Z_$])[a-zA-Z_$\d]*|[a-zA-Z_$][a-zA-Z_$\d]*:|self|arguments|'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"/, ''
|
|
49
|
-
).scan(
|
|
50
|
-
/([a-z_$][a-z_$\d]*)/i
|
|
51
|
-
) do |v|
|
|
52
|
-
params.push(v) unless params.include?(v)
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
eval "Proc.new { |#{params.join(', ')}| #{expr} }", block && block.binding
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
22
|
end
|
data/ruleby.gemspec
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Gem::Specification.new do |s|
|
|
2
|
+
s.name = %q{ruleby}
|
|
3
|
+
s.version = "0.9.b7"
|
|
4
|
+
|
|
5
|
+
s.authors = [%q{Joe Kutner}, %q{Matt Smith}]
|
|
6
|
+
s.description = %q{Ruleby is a rule engine written in the Ruby language. It is a system for executing a set
|
|
7
|
+
of IF-THEN statements known as production rules. These rules are matched to objects using
|
|
8
|
+
the forward chaining Rete algorithm. Ruleby provides an internal Domain Specific Language
|
|
9
|
+
(DSL) for building the productions that make up a Ruleby program.
|
|
10
|
+
}
|
|
11
|
+
s.email = %q{jpkutner@gmail.com}
|
|
12
|
+
s.homepage = %q{http://ruleby.org}
|
|
13
|
+
s.files = `git ls-files`.split("\n")
|
|
14
|
+
s.require_paths = [%q{lib}]
|
|
15
|
+
s.rubyforge_project = %q{ruleby}
|
|
16
|
+
s.summary = %q{Rete based Ruby Rule Engine}
|
|
17
|
+
end
|
data/spec/and_or_spec.rb
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
class AndOrFact
|
|
4
|
+
attr :value, true
|
|
5
|
+
def initialize(v=nil); @value = v; end
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class AndOrFact2
|
|
9
|
+
attr :value, true
|
|
10
|
+
def initialize(v=nil); @value = v; end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class AndOrFact3
|
|
14
|
+
attr :value, true
|
|
15
|
+
def initialize(v=nil); @value = v; end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class AndOrFact4
|
|
19
|
+
attr :value, true
|
|
20
|
+
def initialize(v=nil); @value = v; end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class AndOrFact5
|
|
24
|
+
attr :value, true
|
|
25
|
+
def initialize(v=nil); @value = v; end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class AndOrFact6
|
|
29
|
+
attr :value, true
|
|
30
|
+
def initialize(v=nil); @value = v; end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
include Ruleby
|
|
34
|
+
|
|
35
|
+
class AndOrRulebook < Rulebook
|
|
36
|
+
def rules
|
|
37
|
+
rule AND(
|
|
38
|
+
OR([AndOrFact, m.value > 0]),
|
|
39
|
+
OR(
|
|
40
|
+
OR([AndOrFact, m.value == 1]),
|
|
41
|
+
AND(
|
|
42
|
+
AND([AndOrFact, m.value < 1]),
|
|
43
|
+
OR([AndOrFact, m.value == nil], [:not, AndOrFact])))) do
|
|
44
|
+
assert Success.new
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# rule [AndOrFact, m.value > 0],
|
|
48
|
+
# OR(
|
|
49
|
+
# [AndOrFact, m.value == 1],
|
|
50
|
+
# AND(
|
|
51
|
+
# [AndOrFact, m.value < 1],
|
|
52
|
+
# OR([AndOrFact, m.value == nil], [:not, AndOrFact]))) do
|
|
53
|
+
# assert Success.new
|
|
54
|
+
# end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def rules2
|
|
58
|
+
rule OR(AND(OR(OR([AndOrFact, m.value == 1])))) do |v|
|
|
59
|
+
assert Success.new
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def rules3
|
|
64
|
+
rule OR([AndOrFact, m.value == 1], [AndOrFact, m.value == 2], [AndOrFact, m.value == 3]), [AndOrFact, m.value == 4] do |v|
|
|
65
|
+
assert Success.new
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def rules4
|
|
70
|
+
rule AND([AndOrFact, :a, m.value == 1], [AndOrFact2, :a2, m.value == 2]) do |v|
|
|
71
|
+
raise "nil" if v[:a].nil?
|
|
72
|
+
raise "nil" if v[:a2].nil?
|
|
73
|
+
assert Success.new
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def rules5
|
|
78
|
+
rule OR(AND([AndOrFact, :a, {m.value == 1 => :x}], [AndOrFact2, m.value == b(:x)])) do |v|
|
|
79
|
+
assert Success.new
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def rules6
|
|
84
|
+
rule OR(
|
|
85
|
+
AND([:collect, AndOrFact, m.value == 1]),
|
|
86
|
+
AND([:collect, AndOrFact2, m.value == 2])
|
|
87
|
+
), AND(
|
|
88
|
+
AND([AndOrFact3, m.value == 65]),
|
|
89
|
+
OR(
|
|
90
|
+
OR(
|
|
91
|
+
OR([AndOrFact4, m.value == 4]),
|
|
92
|
+
AND([AndOrFact5, m.value == 5])
|
|
93
|
+
),
|
|
94
|
+
OR([AndOrFact6, m.value == 6])
|
|
95
|
+
)
|
|
96
|
+
) do |v|
|
|
97
|
+
assert Success.new
|
|
98
|
+
end
|
|
99
|
+
# all that really matters
|
|
100
|
+
# rule OR(
|
|
101
|
+
# [AndOrFact, m.value == 1],
|
|
102
|
+
# [AndOrFact2, m.value == 2]
|
|
103
|
+
# ), AND(
|
|
104
|
+
# [AndOrFact3, m.value == 65],
|
|
105
|
+
# OR(
|
|
106
|
+
# [AndOrFact4, m.value == 4],
|
|
107
|
+
# [AndOrFact5, m.value == 5]
|
|
108
|
+
# )
|
|
109
|
+
# ) do |v|
|
|
110
|
+
# assert Success.new
|
|
111
|
+
# end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
describe Ruleby::Core::Engine do
|
|
116
|
+
# describe "AND/OR" do
|
|
117
|
+
context "crazy AND/OR rules" do
|
|
118
|
+
subject do
|
|
119
|
+
engine :engine do |e|
|
|
120
|
+
AndOrRulebook.new(e).rules
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
before do
|
|
125
|
+
subject.assert AndOrFact.new(1)
|
|
126
|
+
subject.match
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it "should have matched" do
|
|
130
|
+
subject.errors.should == []
|
|
131
|
+
subject.retrieve(Success).size.should == 1
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
context "nested AND/OR rule" do
|
|
136
|
+
subject do
|
|
137
|
+
engine :engine do |e|
|
|
138
|
+
AndOrRulebook.new(e).rules2
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
before do
|
|
143
|
+
subject.assert AndOrFact.new(1)
|
|
144
|
+
subject.match
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it "should have matched" do
|
|
148
|
+
subject.errors.should == []
|
|
149
|
+
subject.retrieve(Success).size.should == 1
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
context "multi OR rule" do
|
|
154
|
+
subject do
|
|
155
|
+
engine :engine do |e|
|
|
156
|
+
AndOrRulebook.new(e).rules3
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
context "with one 1 and one 4" do
|
|
161
|
+
before do
|
|
162
|
+
subject.assert AndOrFact.new(1)
|
|
163
|
+
subject.assert AndOrFact.new(4)
|
|
164
|
+
subject.match
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
it "should have matched" do
|
|
168
|
+
subject.errors.should == []
|
|
169
|
+
subject.retrieve(Success).size.should == 1
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
context "nested AND/OR rule" do
|
|
175
|
+
subject do
|
|
176
|
+
engine :engine do |e|
|
|
177
|
+
AndOrRulebook.new(e).rules4
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
before do
|
|
182
|
+
subject.assert AndOrFact.new(1)
|
|
183
|
+
subject.assert AndOrFact2.new(2)
|
|
184
|
+
subject.match
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
it "should have matched" do
|
|
188
|
+
subject.errors.should == []
|
|
189
|
+
subject.retrieve(Success).size.should == 1
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
context "nested AND/OR rule" do
|
|
194
|
+
subject do
|
|
195
|
+
engine :engine do |e|
|
|
196
|
+
AndOrRulebook.new(e).rules5
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
before do
|
|
201
|
+
subject.assert AndOrFact.new(1)
|
|
202
|
+
subject.assert AndOrFact2.new(1)
|
|
203
|
+
subject.match
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
it "should have matched" do
|
|
207
|
+
subject.errors.should == []
|
|
208
|
+
subject.retrieve(Success).size.should == 1
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
context "another crazy nested AND/OR rule" do
|
|
213
|
+
subject do
|
|
214
|
+
engine :engine do |e|
|
|
215
|
+
AndOrRulebook.new(e).rules6
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
before do
|
|
220
|
+
subject.assert AndOrFact.new(1)
|
|
221
|
+
subject.assert AndOrFact3.new(3)
|
|
222
|
+
subject.assert AndOrFact4.new(4)
|
|
223
|
+
subject.match
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
it "should not have matched" do
|
|
227
|
+
subject.errors.should == []
|
|
228
|
+
subject.retrieve(Success).size.should == 0
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
context "another crazy nested AND/OR rule" do
|
|
233
|
+
subject do
|
|
234
|
+
engine :engine do |e|
|
|
235
|
+
AndOrRulebook.new(e).rules6
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
before do
|
|
240
|
+
subject.assert AndOrFact.new(1)
|
|
241
|
+
subject.assert AndOrFact3.new(65)
|
|
242
|
+
subject.assert AndOrFact4.new(4)
|
|
243
|
+
subject.match
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
it "should have matched" do
|
|
247
|
+
subject.errors.should == []
|
|
248
|
+
subject.retrieve(Success).size.should == 1
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
# end
|
|
252
|
+
end
|
|
@@ -0,0 +1,1021 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
class A
|
|
4
|
+
attr :value, true
|
|
5
|
+
def initialize(v=nil); @value = v; end
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class B
|
|
9
|
+
attr :value1, true
|
|
10
|
+
attr :value2, true
|
|
11
|
+
def initialize(v1=nil, v2=nil); @value1 = v1; @value2 = v2; end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class C
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
include Ruleby
|
|
19
|
+
|
|
20
|
+
class CollectRulebook < Rulebook
|
|
21
|
+
def rules_with_one_pattern
|
|
22
|
+
rule [:collect, A, :a] do |v|
|
|
23
|
+
assert v[:a]
|
|
24
|
+
assert Success.new
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def rules_with_one_pattern_and_other_conditions
|
|
29
|
+
rule [:collect, A, :a, m.value == "foo"] do |v|
|
|
30
|
+
assert v[:a]
|
|
31
|
+
assert Success.new
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
rule [:collect, B, :b, m.value1 == "foo", m.value2 == "bar"] do |v|
|
|
35
|
+
assert v[:b]
|
|
36
|
+
assert Success.new
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def rules_with_one_pattern_inside_and
|
|
41
|
+
rule AND([:collect, A, :a]) do |v|
|
|
42
|
+
assert v[:a]
|
|
43
|
+
assert Success.new
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def rules_with_two_collect_patterns_of_same_type
|
|
48
|
+
rule [:collect, A, :a1], [:collect, A, :a2] do |v|
|
|
49
|
+
assert v[:a1]
|
|
50
|
+
assert v[:a2]
|
|
51
|
+
assert Success.new
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def rules_with_two_collect_patterns_of_different_type
|
|
56
|
+
rule [:collect, A, :a], [:collect, B, :b] do |v|
|
|
57
|
+
assert v[:a]
|
|
58
|
+
assert v[:b]
|
|
59
|
+
assert Success.new
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def rules_with_one_pattern_and_a_not_on_right
|
|
64
|
+
rule [:collect, A, :a], [:not, B] do |v|
|
|
65
|
+
assert v[:a]
|
|
66
|
+
assert Success.new
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def rules_with_one_pattern_and_a_not_on_left
|
|
71
|
+
rule [:not, B], [:collect, A, :a] do |v|
|
|
72
|
+
assert v[:a]
|
|
73
|
+
assert Success.new
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def rules_with_more_than_one_pattern
|
|
78
|
+
rule [:collect, A, :a], [B, :b] do |v|
|
|
79
|
+
assert v[:a]
|
|
80
|
+
assert Success.new(:right)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
rule [B, :b], [:collect, A, :a] do |v|
|
|
84
|
+
assert v[:a]
|
|
85
|
+
assert Success.new(:left)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def rules_with_more_than_one_pattern_on_each_side
|
|
90
|
+
rule [B, :b], [:collect, A, :a], [C, :c] do |v|
|
|
91
|
+
assert v[:a]
|
|
92
|
+
assert Success.new
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def rules_with_chaining
|
|
97
|
+
rule [:collect, A, :a] do |v|
|
|
98
|
+
assert v[:a]
|
|
99
|
+
assert Success.new
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
rule [C, :c] do |v|
|
|
103
|
+
assert A.new
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def rules_with_binding
|
|
108
|
+
rule [:collect, A, :a], [B, :b, m.value1(:a, &c{|v1, a| a.size > 0 and a[0].object.value == v1})] do |v|
|
|
109
|
+
assert Success.new
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
rule [:collect, A, :a], [B, :b, m.value1(:a, &c{|v1, a| a.size > 1 and a[0].object.value == v1})] do |v|
|
|
113
|
+
assert Success.new
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def rules_with_chaining_and_binding
|
|
118
|
+
rule [:collect, A, :a], [B, :b, m.value1(:a, &c{|v1, a| a.size > 0})] do |v|
|
|
119
|
+
assert v[:a]
|
|
120
|
+
assert Success.new
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
rule [C, :c] do |v|
|
|
124
|
+
assert A.new
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
describe Ruleby::Core::Engine do
|
|
130
|
+
|
|
131
|
+
describe ":collect" do
|
|
132
|
+
|
|
133
|
+
shared_examples_for "not patterns with [:collect, A] and [:not, B] when there is a B" do
|
|
134
|
+
it "should not match" do
|
|
135
|
+
s = subject.retrieve Success
|
|
136
|
+
s.should_not be_nil
|
|
137
|
+
s.size.should == 0
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it "should match once B is retracted" do
|
|
141
|
+
a = subject.retrieve B
|
|
142
|
+
subject.retract a[0]
|
|
143
|
+
|
|
144
|
+
subject.match
|
|
145
|
+
|
|
146
|
+
s = subject.retrieve Success
|
|
147
|
+
s.size.should == 1
|
|
148
|
+
a = subject.retrieve A
|
|
149
|
+
a.size.should == 2
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
shared_examples_for "one :collect A rule and one A" do
|
|
154
|
+
it "should retrieve Success" do
|
|
155
|
+
s = subject.retrieve Success
|
|
156
|
+
s.should_not be_nil
|
|
157
|
+
s.size.should == 1
|
|
158
|
+
|
|
159
|
+
s = subject.retrieve Array
|
|
160
|
+
s.should_not be_nil
|
|
161
|
+
s.size.should == 1
|
|
162
|
+
|
|
163
|
+
a = s[0]
|
|
164
|
+
a.size.should == 1
|
|
165
|
+
a[0].object.class.should == A
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it "should retract without error" do
|
|
169
|
+
s = subject.retrieve Success
|
|
170
|
+
s.size.should == 1
|
|
171
|
+
subject.retract s[0]
|
|
172
|
+
|
|
173
|
+
a = subject.retrieve A
|
|
174
|
+
a.size.should == 1
|
|
175
|
+
subject.retract a[0]
|
|
176
|
+
|
|
177
|
+
subject.match
|
|
178
|
+
|
|
179
|
+
s = subject.retrieve Success
|
|
180
|
+
s.size.should == 0
|
|
181
|
+
a = subject.retrieve A
|
|
182
|
+
a.size.should == 0
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
shared_examples_for "one :collect A rule and two As" do
|
|
187
|
+
it "should retrieve Success" do
|
|
188
|
+
s = subject.retrieve Success
|
|
189
|
+
s.should_not be_nil
|
|
190
|
+
s.size.should == 1
|
|
191
|
+
|
|
192
|
+
s = subject.retrieve Array
|
|
193
|
+
s.should_not be_nil
|
|
194
|
+
s.size.should == 1
|
|
195
|
+
|
|
196
|
+
a = s[0]
|
|
197
|
+
a.size.should == 2
|
|
198
|
+
a[0].object.class.should == A
|
|
199
|
+
a[1].object.class.should == A
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
it "should retract without error" do
|
|
203
|
+
s = subject.retrieve Success
|
|
204
|
+
subject.retract s[0]
|
|
205
|
+
a = subject.retrieve A
|
|
206
|
+
subject.retract a[0]
|
|
207
|
+
|
|
208
|
+
subject.match
|
|
209
|
+
|
|
210
|
+
s = subject.retrieve Success
|
|
211
|
+
s.size.should == 1
|
|
212
|
+
a = subject.retrieve A
|
|
213
|
+
a.size.should == 1
|
|
214
|
+
|
|
215
|
+
s = subject.retrieve Success
|
|
216
|
+
subject.retract s[0]
|
|
217
|
+
a = subject.retrieve A
|
|
218
|
+
subject.retract a[0]
|
|
219
|
+
|
|
220
|
+
subject.match
|
|
221
|
+
|
|
222
|
+
s = subject.retrieve Success
|
|
223
|
+
s.size.should == 0
|
|
224
|
+
a = subject.retrieve A
|
|
225
|
+
a.size.should == 0
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
context "as one pattern" do
|
|
230
|
+
subject do
|
|
231
|
+
engine :engine do |e|
|
|
232
|
+
CollectRulebook.new(e).rules_with_one_pattern
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
context "with one A" do
|
|
237
|
+
before do
|
|
238
|
+
subject.assert A.new
|
|
239
|
+
subject.match
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
it_should_behave_like "one :collect A rule and one A"
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
context "with more than one A" do
|
|
246
|
+
before do
|
|
247
|
+
subject.assert A.new
|
|
248
|
+
subject.assert A.new
|
|
249
|
+
subject.match
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
it_should_behave_like "one :collect A rule and two As"
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
context "as one pattern and other conditions" do
|
|
257
|
+
subject do
|
|
258
|
+
engine :engine do |e|
|
|
259
|
+
CollectRulebook.new(e).rules_with_one_pattern_and_other_conditions
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
context "with one A('foo')" do
|
|
264
|
+
before do
|
|
265
|
+
subject.assert A.new("foo")
|
|
266
|
+
subject.match
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
it_should_behave_like "one :collect A rule and one A"
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
context "with more than one A('foo')" do
|
|
273
|
+
before do
|
|
274
|
+
subject.assert A.new("foo")
|
|
275
|
+
subject.assert A.new("foo")
|
|
276
|
+
subject.match
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
it_should_behave_like "one :collect A rule and two As"
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
context "with one A('foo') and one A(nil)" do
|
|
283
|
+
before do
|
|
284
|
+
subject.assert A.new("foo")
|
|
285
|
+
subject.assert A.new
|
|
286
|
+
subject.match
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
it "should retrieve Success" do
|
|
290
|
+
s = subject.retrieve Success
|
|
291
|
+
s.should_not be_nil
|
|
292
|
+
s.size.should == 1
|
|
293
|
+
|
|
294
|
+
s = subject.retrieve Array
|
|
295
|
+
s.should_not be_nil
|
|
296
|
+
s.size.should == 1
|
|
297
|
+
|
|
298
|
+
a = s[0]
|
|
299
|
+
a.size.should == 1
|
|
300
|
+
a[0].object.class.should == A
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
context "with more than one A('foo') and one A(nil)" do
|
|
305
|
+
before do
|
|
306
|
+
subject.assert A.new("foo")
|
|
307
|
+
subject.assert A.new("foo")
|
|
308
|
+
subject.assert A.new
|
|
309
|
+
subject.match
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
it "should retrieve Success" do
|
|
313
|
+
s = subject.retrieve Success
|
|
314
|
+
s.should_not be_nil
|
|
315
|
+
s.size.should == 1
|
|
316
|
+
|
|
317
|
+
s = subject.retrieve Array
|
|
318
|
+
s.should_not be_nil
|
|
319
|
+
s.size.should == 1
|
|
320
|
+
|
|
321
|
+
a = s[0]
|
|
322
|
+
a.size.should == 2
|
|
323
|
+
a[0].object.class.should == A
|
|
324
|
+
a[1].object.class.should == A
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
context "with one A(nil)" do
|
|
329
|
+
before do
|
|
330
|
+
subject.assert A.new
|
|
331
|
+
subject.match
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
it "should not succeed" do
|
|
335
|
+
s = subject.retrieve Success
|
|
336
|
+
s.should_not be_nil
|
|
337
|
+
s.size.should == 0
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
context "with one B(foo,nil)" do
|
|
342
|
+
before do
|
|
343
|
+
subject.assert B.new("foo")
|
|
344
|
+
subject.match
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
it "should not succeed" do
|
|
348
|
+
s = subject.retrieve Success
|
|
349
|
+
s.should_not be_nil
|
|
350
|
+
s.size.should == 0
|
|
351
|
+
end
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
context "with one B(foo,bar)" do
|
|
355
|
+
before do
|
|
356
|
+
subject.assert B.new("foo", "bar")
|
|
357
|
+
subject.match
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
it "should not succeed" do
|
|
361
|
+
s = subject.retrieve Success
|
|
362
|
+
s.should_not be_nil
|
|
363
|
+
s.size.should == 1
|
|
364
|
+
end
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
context "with one B(foo,bar) and one B(foo,nil)" do
|
|
368
|
+
before do
|
|
369
|
+
subject.assert B.new("foo", "bar")
|
|
370
|
+
subject.assert B.new("foo", "bar")
|
|
371
|
+
subject.assert B.new("foo")
|
|
372
|
+
subject.match
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
it "should succeed" do
|
|
376
|
+
s = subject.retrieve Success
|
|
377
|
+
s.should_not be_nil
|
|
378
|
+
s.size.should == 1
|
|
379
|
+
|
|
380
|
+
s = subject.retrieve Array
|
|
381
|
+
s.should_not be_nil
|
|
382
|
+
s.size.should == 1
|
|
383
|
+
|
|
384
|
+
a = s[0]
|
|
385
|
+
a.size.should == 2
|
|
386
|
+
a[0].object.class.should == B
|
|
387
|
+
a[1].object.class.should == B
|
|
388
|
+
end
|
|
389
|
+
end
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
context "as one pattern inside AND" do
|
|
393
|
+
subject do
|
|
394
|
+
engine :engine do |e|
|
|
395
|
+
CollectRulebook.new(e).rules_with_one_pattern_inside_and
|
|
396
|
+
end
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
context "with one A" do
|
|
400
|
+
before do
|
|
401
|
+
subject.assert A.new
|
|
402
|
+
subject.match
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
it_should_behave_like "one :collect A rule and one A"
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
context "with more than one A" do
|
|
409
|
+
before do
|
|
410
|
+
subject.assert A.new
|
|
411
|
+
subject.assert A.new
|
|
412
|
+
subject.match
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
it_should_behave_like "one :collect A rule and two As"
|
|
416
|
+
end
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
context "as two patterns of same type" do
|
|
420
|
+
subject do
|
|
421
|
+
engine :engine do |e|
|
|
422
|
+
CollectRulebook.new(e).rules_with_two_collect_patterns_of_same_type
|
|
423
|
+
end
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
context "with one A" do
|
|
427
|
+
before do
|
|
428
|
+
subject.assert A.new
|
|
429
|
+
subject.match
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
it "should match" do
|
|
433
|
+
s = subject.retrieve Success
|
|
434
|
+
s.should_not be_nil
|
|
435
|
+
s.size.should == 1
|
|
436
|
+
|
|
437
|
+
s = subject.retrieve Array
|
|
438
|
+
s.should_not be_nil
|
|
439
|
+
s.size.should == 2
|
|
440
|
+
|
|
441
|
+
a = s[0]
|
|
442
|
+
a.size.should == 1
|
|
443
|
+
a[0].object.class.should == A
|
|
444
|
+
|
|
445
|
+
a = s[1]
|
|
446
|
+
a.size.should == 1
|
|
447
|
+
a[0].object.class.should == A
|
|
448
|
+
end
|
|
449
|
+
end
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
context "as two patterns of different type" do
|
|
453
|
+
subject do
|
|
454
|
+
engine :engine do |e|
|
|
455
|
+
CollectRulebook.new(e).rules_with_two_collect_patterns_of_different_type
|
|
456
|
+
end
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
context "with one A" do
|
|
460
|
+
before do
|
|
461
|
+
subject.assert A.new
|
|
462
|
+
subject.match
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
it "should not match" do
|
|
466
|
+
s = subject.retrieve Success
|
|
467
|
+
s.should_not be_nil
|
|
468
|
+
s.size.should == 0
|
|
469
|
+
end
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
context "with one A and one B" do
|
|
473
|
+
before do
|
|
474
|
+
subject.assert A.new
|
|
475
|
+
subject.assert B.new
|
|
476
|
+
subject.match
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
it "should not match" do
|
|
480
|
+
s = subject.retrieve Success
|
|
481
|
+
s.should_not be_nil
|
|
482
|
+
s.size.should == 1
|
|
483
|
+
|
|
484
|
+
s = subject.retrieve Array
|
|
485
|
+
s.should_not be_nil
|
|
486
|
+
s.size.should == 2
|
|
487
|
+
|
|
488
|
+
classes = []
|
|
489
|
+
|
|
490
|
+
a = s[0]
|
|
491
|
+
a.size.should == 1
|
|
492
|
+
classes << a[0].object.class
|
|
493
|
+
|
|
494
|
+
a = s[1]
|
|
495
|
+
a.size.should == 1
|
|
496
|
+
classes << a[0].object.class
|
|
497
|
+
|
|
498
|
+
classes.should include(A, B)
|
|
499
|
+
end
|
|
500
|
+
end
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
context "as one pattern and a not on left" do
|
|
504
|
+
subject do
|
|
505
|
+
engine :engine do |e|
|
|
506
|
+
CollectRulebook.new(e).rules_with_one_pattern_and_a_not_on_left
|
|
507
|
+
end
|
|
508
|
+
end
|
|
509
|
+
|
|
510
|
+
context "with one A" do
|
|
511
|
+
before do
|
|
512
|
+
subject.assert A.new
|
|
513
|
+
subject.match
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
it_should_behave_like "one :collect A rule and one A"
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
context "with more than one A" do
|
|
520
|
+
before do
|
|
521
|
+
subject.assert A.new
|
|
522
|
+
subject.assert A.new
|
|
523
|
+
subject.match
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
it_should_behave_like "one :collect A rule and two As"
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
context "with more than one A and a B" do
|
|
530
|
+
before do
|
|
531
|
+
subject.assert A.new
|
|
532
|
+
subject.assert A.new
|
|
533
|
+
subject.assert B.new
|
|
534
|
+
subject.match
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
it_should_behave_like "not patterns with [:collect, A] and [:not, B] when there is a B"
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
context "with more than one A and a B" do
|
|
541
|
+
before do
|
|
542
|
+
subject.assert B.new
|
|
543
|
+
subject.assert A.new
|
|
544
|
+
subject.assert A.new
|
|
545
|
+
subject.match
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
it_should_behave_like "not patterns with [:collect, A] and [:not, B] when there is a B"
|
|
549
|
+
end
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
context "as one pattern and a not on right" do
|
|
553
|
+
subject do
|
|
554
|
+
engine :engine do |e|
|
|
555
|
+
CollectRulebook.new(e).rules_with_one_pattern_and_a_not_on_right
|
|
556
|
+
end
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
context "with one A" do
|
|
560
|
+
before do
|
|
561
|
+
subject.assert A.new
|
|
562
|
+
subject.match
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
it_should_behave_like "one :collect A rule and one A"
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
context "with more than one A" do
|
|
569
|
+
before do
|
|
570
|
+
subject.assert A.new
|
|
571
|
+
subject.assert A.new
|
|
572
|
+
subject.match
|
|
573
|
+
end
|
|
574
|
+
|
|
575
|
+
it_should_behave_like "one :collect A rule and two As"
|
|
576
|
+
end
|
|
577
|
+
|
|
578
|
+
context "with more than one A's first and a B" do
|
|
579
|
+
before do
|
|
580
|
+
subject.assert A.new
|
|
581
|
+
subject.assert A.new
|
|
582
|
+
subject.assert B.new
|
|
583
|
+
subject.match
|
|
584
|
+
end
|
|
585
|
+
|
|
586
|
+
it_should_behave_like "not patterns with [:collect, A] and [:not, B] when there is a B"
|
|
587
|
+
end
|
|
588
|
+
|
|
589
|
+
context "with more than one A and a B first" do
|
|
590
|
+
before do
|
|
591
|
+
subject.assert B.new
|
|
592
|
+
subject.assert A.new
|
|
593
|
+
subject.assert A.new
|
|
594
|
+
subject.match
|
|
595
|
+
end
|
|
596
|
+
|
|
597
|
+
it_should_behave_like "not patterns with [:collect, A] and [:not, B] when there is a B"
|
|
598
|
+
end
|
|
599
|
+
end
|
|
600
|
+
|
|
601
|
+
context "as two patterns" do
|
|
602
|
+
subject do
|
|
603
|
+
engine :engine do |e|
|
|
604
|
+
CollectRulebook.new(e).rules_with_more_than_one_pattern
|
|
605
|
+
end
|
|
606
|
+
end
|
|
607
|
+
|
|
608
|
+
context "with one A" do
|
|
609
|
+
before do
|
|
610
|
+
subject.assert A.new
|
|
611
|
+
subject.assert B.new
|
|
612
|
+
subject.match
|
|
613
|
+
end
|
|
614
|
+
|
|
615
|
+
it "should retrieve Success" do
|
|
616
|
+
s = subject.retrieve Success
|
|
617
|
+
s.should_not be_nil
|
|
618
|
+
s.size.should == 2
|
|
619
|
+
|
|
620
|
+
s = subject.retrieve Array
|
|
621
|
+
s.should_not be_nil
|
|
622
|
+
s.size.should == 2
|
|
623
|
+
|
|
624
|
+
a = s[0]
|
|
625
|
+
a.size.should == 1
|
|
626
|
+
a[0].object.class.should == A
|
|
627
|
+
|
|
628
|
+
a = s[1]
|
|
629
|
+
a.size.should == 1
|
|
630
|
+
a[0].object.class.should == A
|
|
631
|
+
end
|
|
632
|
+
end
|
|
633
|
+
|
|
634
|
+
context "with more than one A" do
|
|
635
|
+
before do
|
|
636
|
+
subject.assert A.new
|
|
637
|
+
subject.assert B.new
|
|
638
|
+
subject.assert A.new
|
|
639
|
+
subject.match
|
|
640
|
+
end
|
|
641
|
+
|
|
642
|
+
it "should retrieve Success" do
|
|
643
|
+
s = subject.retrieve Success
|
|
644
|
+
s.should_not be_nil
|
|
645
|
+
s.size.should == 2
|
|
646
|
+
|
|
647
|
+
s = subject.retrieve Array
|
|
648
|
+
s.should_not be_nil
|
|
649
|
+
s.size.should == 2 # one array for each rule
|
|
650
|
+
|
|
651
|
+
a = s[0]
|
|
652
|
+
a.size.should == 2
|
|
653
|
+
a[0].object.class.should == A
|
|
654
|
+
a[1].object.class.should == A
|
|
655
|
+
|
|
656
|
+
a = s[1]
|
|
657
|
+
a.size.should == 2
|
|
658
|
+
a[0].object.class.should == A
|
|
659
|
+
a[1].object.class.should == A
|
|
660
|
+
end
|
|
661
|
+
|
|
662
|
+
it "should retract A without error" do
|
|
663
|
+
s = subject.retrieve Success
|
|
664
|
+
subject.retract s[0]
|
|
665
|
+
subject.retract s[1]
|
|
666
|
+
a = subject.retrieve A
|
|
667
|
+
subject.retract a[0]
|
|
668
|
+
|
|
669
|
+
subject.match
|
|
670
|
+
|
|
671
|
+
s = subject.retrieve Success
|
|
672
|
+
s.size.should == 2
|
|
673
|
+
a = subject.retrieve A
|
|
674
|
+
a.size.should == 1
|
|
675
|
+
|
|
676
|
+
s = subject.retrieve Success
|
|
677
|
+
subject.retract s[0]
|
|
678
|
+
subject.retract s[1]
|
|
679
|
+
a = subject.retrieve A
|
|
680
|
+
subject.retract a[0]
|
|
681
|
+
|
|
682
|
+
subject.match
|
|
683
|
+
|
|
684
|
+
s = subject.retrieve Success
|
|
685
|
+
s.size.should == 0
|
|
686
|
+
a = subject.retrieve A
|
|
687
|
+
a.size.should == 0
|
|
688
|
+
end
|
|
689
|
+
|
|
690
|
+
it "should retract B without error" do
|
|
691
|
+
s = subject.retrieve Success
|
|
692
|
+
subject.retract s[0]
|
|
693
|
+
subject.retract s[1]
|
|
694
|
+
b = subject.retrieve B
|
|
695
|
+
subject.retract b[0]
|
|
696
|
+
|
|
697
|
+
subject.match
|
|
698
|
+
|
|
699
|
+
s = subject.retrieve Success
|
|
700
|
+
s.size.should == 0
|
|
701
|
+
a = subject.retrieve A
|
|
702
|
+
a.size.should == 2
|
|
703
|
+
b = subject.retrieve B
|
|
704
|
+
b.size.should == 0
|
|
705
|
+
end
|
|
706
|
+
end
|
|
707
|
+
end
|
|
708
|
+
|
|
709
|
+
context "as patterns on each side" do
|
|
710
|
+
subject do
|
|
711
|
+
engine :engine do |e|
|
|
712
|
+
CollectRulebook.new(e).rules_with_more_than_one_pattern_on_each_side
|
|
713
|
+
end
|
|
714
|
+
end
|
|
715
|
+
|
|
716
|
+
context "with one A" do
|
|
717
|
+
context "and no C" do
|
|
718
|
+
before do
|
|
719
|
+
subject.assert A.new
|
|
720
|
+
subject.assert B.new
|
|
721
|
+
subject.match
|
|
722
|
+
end
|
|
723
|
+
|
|
724
|
+
it "should retrieve Success" do
|
|
725
|
+
s = subject.retrieve Success
|
|
726
|
+
s.should_not be_nil
|
|
727
|
+
s.size.should == 0
|
|
728
|
+
end
|
|
729
|
+
end
|
|
730
|
+
|
|
731
|
+
context "and all other facts" do
|
|
732
|
+
before do
|
|
733
|
+
subject.assert A.new
|
|
734
|
+
subject.assert B.new
|
|
735
|
+
subject.assert C.new
|
|
736
|
+
subject.match
|
|
737
|
+
end
|
|
738
|
+
|
|
739
|
+
it "should retrieve Success" do
|
|
740
|
+
s = subject.retrieve Success
|
|
741
|
+
s.should_not be_nil
|
|
742
|
+
s.size.should == 1
|
|
743
|
+
|
|
744
|
+
s = subject.retrieve Array
|
|
745
|
+
s.should_not be_nil
|
|
746
|
+
s.size.should == 1
|
|
747
|
+
|
|
748
|
+
a = s[0]
|
|
749
|
+
a.size.should == 1
|
|
750
|
+
a[0].object.class.should == A
|
|
751
|
+
end
|
|
752
|
+
end
|
|
753
|
+
end
|
|
754
|
+
|
|
755
|
+
context "with more than one A" do
|
|
756
|
+
before do
|
|
757
|
+
subject.assert A.new
|
|
758
|
+
subject.assert B.new
|
|
759
|
+
subject.assert C.new
|
|
760
|
+
subject.assert A.new
|
|
761
|
+
subject.match
|
|
762
|
+
end
|
|
763
|
+
|
|
764
|
+
it "should retrieve Success" do
|
|
765
|
+
s = subject.retrieve Success
|
|
766
|
+
s.should_not be_nil
|
|
767
|
+
s.size.should == 1
|
|
768
|
+
|
|
769
|
+
s = subject.retrieve Array
|
|
770
|
+
s.should_not be_nil
|
|
771
|
+
s.size.should == 1
|
|
772
|
+
|
|
773
|
+
a = s[0]
|
|
774
|
+
a.size.should == 2
|
|
775
|
+
a[0].object.class.should == A
|
|
776
|
+
a[1].object.class.should == A
|
|
777
|
+
end
|
|
778
|
+
|
|
779
|
+
it "should retract A without error" do
|
|
780
|
+
s = subject.retrieve Success
|
|
781
|
+
subject.retract s[0]
|
|
782
|
+
a = subject.retrieve A
|
|
783
|
+
subject.retract a[0]
|
|
784
|
+
|
|
785
|
+
subject.match
|
|
786
|
+
|
|
787
|
+
s = subject.retrieve Success
|
|
788
|
+
s.size.should == 1
|
|
789
|
+
a = subject.retrieve A
|
|
790
|
+
a.size.should == 1
|
|
791
|
+
|
|
792
|
+
s = subject.retrieve Success
|
|
793
|
+
subject.retract s[0]
|
|
794
|
+
a = subject.retrieve A
|
|
795
|
+
subject.retract a[0]
|
|
796
|
+
|
|
797
|
+
subject.match
|
|
798
|
+
|
|
799
|
+
s = subject.retrieve Success
|
|
800
|
+
s.size.should == 0
|
|
801
|
+
a = subject.retrieve A
|
|
802
|
+
a.size.should == 0
|
|
803
|
+
end
|
|
804
|
+
|
|
805
|
+
it "should retract B without error" do
|
|
806
|
+
s = subject.retrieve Success
|
|
807
|
+
subject.retract s[0]
|
|
808
|
+
b = subject.retrieve B
|
|
809
|
+
subject.retract b[0]
|
|
810
|
+
|
|
811
|
+
subject.match
|
|
812
|
+
|
|
813
|
+
s = subject.retrieve Success
|
|
814
|
+
s.size.should == 0
|
|
815
|
+
a = subject.retrieve A
|
|
816
|
+
a.size.should == 2
|
|
817
|
+
b = subject.retrieve B
|
|
818
|
+
b.size.should == 0
|
|
819
|
+
end
|
|
820
|
+
|
|
821
|
+
it "should retract C without error" do
|
|
822
|
+
s = subject.retrieve Success
|
|
823
|
+
subject.retract s[0]
|
|
824
|
+
b = subject.retrieve C
|
|
825
|
+
subject.retract b[0]
|
|
826
|
+
|
|
827
|
+
subject.match
|
|
828
|
+
|
|
829
|
+
s = subject.retrieve Success
|
|
830
|
+
s.size.should == 0
|
|
831
|
+
a = subject.retrieve A
|
|
832
|
+
a.size.should == 2
|
|
833
|
+
b = subject.retrieve C
|
|
834
|
+
b.size.should == 0
|
|
835
|
+
end
|
|
836
|
+
end
|
|
837
|
+
end
|
|
838
|
+
|
|
839
|
+
context "as rule chain" do
|
|
840
|
+
subject do
|
|
841
|
+
engine :engine do |e|
|
|
842
|
+
CollectRulebook.new(e).rules_with_chaining
|
|
843
|
+
end
|
|
844
|
+
end
|
|
845
|
+
|
|
846
|
+
context "with one C" do
|
|
847
|
+
before do
|
|
848
|
+
subject.assert C.new
|
|
849
|
+
subject.match
|
|
850
|
+
end
|
|
851
|
+
|
|
852
|
+
it "should retrieve Success" do
|
|
853
|
+
s = subject.retrieve Success
|
|
854
|
+
s.should_not be_nil
|
|
855
|
+
s.size.should == 1
|
|
856
|
+
|
|
857
|
+
s = subject.retrieve Array
|
|
858
|
+
s.should_not be_nil
|
|
859
|
+
s.size.should == 1
|
|
860
|
+
|
|
861
|
+
a = s[0]
|
|
862
|
+
a.size.should == 1
|
|
863
|
+
a[0].object.class.should == A
|
|
864
|
+
end
|
|
865
|
+
end
|
|
866
|
+
|
|
867
|
+
context "with many C's" do
|
|
868
|
+
before do
|
|
869
|
+
subject.assert C.new
|
|
870
|
+
subject.assert C.new
|
|
871
|
+
subject.assert C.new
|
|
872
|
+
subject.assert C.new
|
|
873
|
+
subject.assert C.new
|
|
874
|
+
subject.match
|
|
875
|
+
end
|
|
876
|
+
|
|
877
|
+
it "should retrieve Success" do
|
|
878
|
+
s = subject.retrieve Success
|
|
879
|
+
s.should_not be_nil
|
|
880
|
+
s.size.should == 1
|
|
881
|
+
|
|
882
|
+
s = subject.retrieve Array
|
|
883
|
+
s.should_not be_nil
|
|
884
|
+
s.size.should == 1
|
|
885
|
+
|
|
886
|
+
a = s[0]
|
|
887
|
+
a.size.should == 5
|
|
888
|
+
a[0].object.class.should == A
|
|
889
|
+
end
|
|
890
|
+
end
|
|
891
|
+
end
|
|
892
|
+
|
|
893
|
+
context "with rule binding" do
|
|
894
|
+
subject do
|
|
895
|
+
engine :engine do |e|
|
|
896
|
+
CollectRulebook.new(e).rules_with_binding
|
|
897
|
+
end
|
|
898
|
+
end
|
|
899
|
+
|
|
900
|
+
context "with one A and one B that have == values" do
|
|
901
|
+
before do
|
|
902
|
+
a = A.new
|
|
903
|
+
a.value = 1
|
|
904
|
+
b = B.new
|
|
905
|
+
b.value1 = 1
|
|
906
|
+
subject.assert b
|
|
907
|
+
subject.assert a
|
|
908
|
+
subject.match
|
|
909
|
+
end
|
|
910
|
+
|
|
911
|
+
it "should retrieve Success" do
|
|
912
|
+
s = subject.retrieve Success
|
|
913
|
+
s.size.should == 1
|
|
914
|
+
end
|
|
915
|
+
end
|
|
916
|
+
|
|
917
|
+
context "with one A and one B that have == values asserted in reverse order" do
|
|
918
|
+
before do
|
|
919
|
+
a = A.new
|
|
920
|
+
a.value = 1
|
|
921
|
+
b = B.new
|
|
922
|
+
b.value1 = 1
|
|
923
|
+
subject.assert a
|
|
924
|
+
subject.assert b
|
|
925
|
+
subject.match
|
|
926
|
+
end
|
|
927
|
+
|
|
928
|
+
it "should retrieve Success" do
|
|
929
|
+
s = subject.retrieve Success
|
|
930
|
+
s.size.should == 1
|
|
931
|
+
end
|
|
932
|
+
end
|
|
933
|
+
|
|
934
|
+
context "with one A and one B that have != values" do
|
|
935
|
+
before do
|
|
936
|
+
a = A.new
|
|
937
|
+
a.value = 1
|
|
938
|
+
b = B.new
|
|
939
|
+
b.value1 = 42
|
|
940
|
+
subject.assert a
|
|
941
|
+
subject.assert b
|
|
942
|
+
subject.match
|
|
943
|
+
end
|
|
944
|
+
|
|
945
|
+
it "should retrieve Success" do
|
|
946
|
+
s = subject.retrieve Success
|
|
947
|
+
s.size.should == 0
|
|
948
|
+
end
|
|
949
|
+
end
|
|
950
|
+
|
|
951
|
+
context "with one A and one B that have != values" do
|
|
952
|
+
before do
|
|
953
|
+
a1 = A.new
|
|
954
|
+
a1.value = 1
|
|
955
|
+
b1 = B.new
|
|
956
|
+
b1.value1 = 1
|
|
957
|
+
a2 = A.new
|
|
958
|
+
a2.value = 1
|
|
959
|
+
subject.assert a1
|
|
960
|
+
subject.assert b1
|
|
961
|
+
subject.assert a2
|
|
962
|
+
subject.match
|
|
963
|
+
end
|
|
964
|
+
|
|
965
|
+
it "should retrieve Success" do
|
|
966
|
+
s = subject.retrieve Success
|
|
967
|
+
s.size.should == 2
|
|
968
|
+
end
|
|
969
|
+
end
|
|
970
|
+
end
|
|
971
|
+
|
|
972
|
+
|
|
973
|
+
context "as rule chain with binding" do
|
|
974
|
+
subject do
|
|
975
|
+
engine :engine do |e|
|
|
976
|
+
CollectRulebook.new(e).rules_with_chaining_and_binding
|
|
977
|
+
end
|
|
978
|
+
end
|
|
979
|
+
|
|
980
|
+
context "with one B and one C" do
|
|
981
|
+
before do
|
|
982
|
+
subject.assert B.new
|
|
983
|
+
subject.assert C.new
|
|
984
|
+
subject.match
|
|
985
|
+
end
|
|
986
|
+
|
|
987
|
+
it "should retrieve Success" do
|
|
988
|
+
subject.retrieve(Success).size.should == 1
|
|
989
|
+
end
|
|
990
|
+
end
|
|
991
|
+
|
|
992
|
+
context "with many C's and two B" do
|
|
993
|
+
before do
|
|
994
|
+
subject.assert C.new
|
|
995
|
+
subject.assert C.new
|
|
996
|
+
subject.assert B.new
|
|
997
|
+
subject.assert C.new
|
|
998
|
+
subject.assert C.new
|
|
999
|
+
subject.assert C.new
|
|
1000
|
+
subject.assert B.new
|
|
1001
|
+
subject.match
|
|
1002
|
+
end
|
|
1003
|
+
|
|
1004
|
+
it "should retrieve Success" do
|
|
1005
|
+
subject.retrieve(Success).size.should == 2
|
|
1006
|
+
|
|
1007
|
+
s = subject.retrieve Array
|
|
1008
|
+
s.size.should == 2
|
|
1009
|
+
|
|
1010
|
+
a = s[0]
|
|
1011
|
+
a.size.should == 5
|
|
1012
|
+
a.each {|o| o.object.class.should == A }
|
|
1013
|
+
|
|
1014
|
+
a = s[1]
|
|
1015
|
+
a.size.should == 5
|
|
1016
|
+
a.each {|o| o.object.class.should == A }
|
|
1017
|
+
end
|
|
1018
|
+
end
|
|
1019
|
+
end
|
|
1020
|
+
end
|
|
1021
|
+
end
|