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.
Files changed (48) hide show
  1. data/.gitignore +5 -0
  2. data/GPL.txt +341 -0
  3. data/LICENSE.txt +52 -0
  4. data/README.markdown +22 -0
  5. data/benchmarks/basic_rules.rb +61 -0
  6. data/benchmarks/joined_rules.rb +66 -0
  7. data/benchmarks/miss_manners/data.rb +146 -0
  8. data/benchmarks/miss_manners/miss_manners.rb +33 -0
  9. data/benchmarks/miss_manners/model.rb +193 -0
  10. data/benchmarks/miss_manners/rules.rb +105 -0
  11. data/benchmarks/model.rb +36 -0
  12. data/examples/diagnosis.rb +129 -0
  13. data/examples/fibonacci_example1.rb +44 -0
  14. data/examples/fibonacci_example2.rb +40 -0
  15. data/examples/fibonacci_example3.rb +78 -0
  16. data/examples/fibonacci_rulebook.rb +84 -0
  17. data/examples/hello.rb +45 -0
  18. data/examples/ticket.rb +113 -0
  19. data/examples/wordgame.rb +107 -0
  20. data/lib/core/engine.rb +26 -24
  21. data/lib/core/nodes.rb +77 -35
  22. data/lib/ruleby.rb +0 -37
  23. data/ruleby.gemspec +17 -0
  24. data/spec/and_or_spec.rb +252 -0
  25. data/spec/coercion_spec.rb +5 -0
  26. data/spec/collect_spec.rb +1021 -0
  27. data/spec/errors_spec.rb +148 -0
  28. data/spec/ferrari_spec.rb +39 -0
  29. data/spec/function_spec.rb +199 -0
  30. data/spec/hello_spec.rb +34 -0
  31. data/spec/node_sharing_spec.rb +53 -0
  32. data/spec/property_spec.rb +69 -0
  33. data/spec/spec.opts +4 -0
  34. data/spec/spec_helper.rb +9 -0
  35. data/tasks/documentation.rake +32 -0
  36. data/tasks/rspec.rake +21 -0
  37. data/tasks/test.rake +9 -0
  38. data/tests/assert_facts.rb +130 -0
  39. data/tests/common.rb +29 -0
  40. data/tests/duck_type.rb +79 -0
  41. data/tests/gets.rb +48 -0
  42. data/tests/join_nodes.rb +63 -0
  43. data/tests/nil.rb +72 -0
  44. data/tests/not_patterns.rb +91 -0
  45. data/tests/or_patterns.rb +154 -0
  46. data/tests/regex.rb +47 -0
  47. data/tests/self_reference.rb +54 -0
  48. metadata +81 -49
@@ -0,0 +1,148 @@
1
+ require 'spec_helper'
2
+
3
+ class A
4
+ attr :value, true
5
+ def initialize(v=nil); @value = v; end
6
+ end
7
+
8
+ include Ruleby
9
+
10
+ class ErrorsRulebook < Rulebook
11
+ def rules_with_method_that_doesnt_exist
12
+ rule [A, :a, m.foobar == 'quack'] do |v|
13
+ assert Success.new
14
+ end
15
+ end
16
+
17
+ def rules_that_raise_errors
18
+ rule [A, :a, m.value(&c{|v| raise ":(" if v == 42; true})] do |v|
19
+ assert Success.new
20
+ end
21
+ end
22
+
23
+ end
24
+
25
+ describe Ruleby::Core::Engine do
26
+
27
+ describe "#errors" do
28
+ context "rules_with_method_that_doesnt_exist" do
29
+ subject do
30
+ engine :engine do |e|
31
+ ErrorsRulebook.new(e).rules_with_method_that_doesnt_exist
32
+ end
33
+ end
34
+
35
+ context "with one A" do
36
+ before do
37
+ subject.assert A.new
38
+ subject.match
39
+ end
40
+
41
+ it "should accumulate an error" do
42
+ r = subject.retrieve Success
43
+ r.size.should == 0
44
+
45
+ errors = subject.errors
46
+ errors.should_not be_nil
47
+ errors.size.should == 1
48
+ errors[0].type.should == :no_method
49
+ errors[0].details[:method].should == :foobar
50
+ errors[0].details[:object].should match /#<A:(.+)>/
51
+ subject.clear_errors
52
+
53
+ subject.errors.should == []
54
+ end
55
+ end
56
+
57
+ context "with one A that quacks" do
58
+ before do
59
+ a = A.new
60
+
61
+ # define a method on the instance (not on the class)
62
+ def a.foobar
63
+ "quack"
64
+ end
65
+
66
+ subject.assert a
67
+ subject.assert A.new
68
+ subject.match
69
+ end
70
+
71
+ it "should accumulate one error" do
72
+ r = subject.retrieve Success
73
+ r.size.should == 1
74
+
75
+ errors = subject.errors
76
+ errors.should_not be_nil
77
+ errors.size.should == 1
78
+ errors[0].type.should == :no_method
79
+ errors[0].details[:method].should == :foobar
80
+ errors[0].details[:object].should match /#<A:(.+)>/
81
+ subject.clear_errors
82
+ end
83
+ end
84
+ end
85
+
86
+
87
+ context "rules_that_raise_errors" do
88
+ subject do
89
+ engine :engine do |e|
90
+ ErrorsRulebook.new(e).rules_that_raise_errors
91
+ end
92
+ end
93
+
94
+ context "with one A where value==42" do
95
+ before do
96
+ a = A.new
97
+ a.value = 42
98
+ subject.assert a
99
+ subject.match
100
+ end
101
+
102
+ it "should accumulate an error" do
103
+ r = subject.retrieve Success
104
+ r.size.should == 0
105
+
106
+ errors = subject.errors
107
+ errors.should_not be_nil
108
+ errors.size.should == 1
109
+ errors[0].type.should == :proc_call
110
+ errors[0].details[:message].should == ':('
111
+ errors[0].details[:object].should match /#<A:(.+)>/
112
+ errors[0].details[:method].should == :value
113
+ errors[0].details[:value].should == "42"
114
+ subject.clear_errors
115
+ end
116
+ end
117
+
118
+ context "with one A where value==42, and one A where value==0" do
119
+ before do
120
+ a1 = A.new
121
+ a1.value = 42
122
+
123
+ a2 = A.new
124
+ a2.value = 0
125
+
126
+ subject.assert a1
127
+ subject.assert a2
128
+ subject.match
129
+ end
130
+
131
+ it "should accumulate one error" do
132
+ r = subject.retrieve Success
133
+ r.size.should == 1
134
+
135
+ errors = subject.errors
136
+ errors.should_not be_nil
137
+ errors.size.should == 1
138
+ errors[0].type.should == :proc_call
139
+ errors[0].details[:message].should == ':('
140
+ errors[0].details[:object].should match /#<A:(.+)>/
141
+ errors[0].details[:method].should == :value
142
+ errors[0].details[:value].should == "42"
143
+ subject.clear_errors
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ class A
4
+
5
+ end
6
+
7
+ include Ruleby
8
+
9
+ class FerrariRulebook < Rulebook
10
+ def rules
11
+ rule [A] do |v|
12
+ assert Success.new
13
+ end
14
+ end
15
+ end
16
+
17
+ describe Ruleby::Core::Engine do
18
+
19
+ subject do
20
+ engine :engine do |e|
21
+ FerrariRulebook.new(e).rules
22
+ end
23
+ end
24
+
25
+ describe "simple case" do
26
+ context "with one A" do
27
+ before do
28
+ subject.assert A.new
29
+ subject.match
30
+ end
31
+
32
+ it "should retrieve Success" do
33
+ s = subject.retrieve Success
34
+ s.should_not be_nil
35
+ s.size.should == 1
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,199 @@
1
+ require 'spec_helper'
2
+
3
+ class FuncFact
4
+ attr :value, true
5
+ attr :times, true
6
+ def initialize(v=nil); @value = v; @times = 0; end
7
+ end
8
+
9
+ include Ruleby
10
+
11
+ class FunctionsRulebook < Rulebook
12
+ def rules_with_simple_function
13
+ rule [FuncFact, :a, f("b", c{|a, b| b == "b"})] do |v|
14
+ assert Success.new
15
+ end
16
+ end
17
+
18
+ def rules_with_function_testing_self(arg)
19
+ rule [FuncFact, :a, f(arg, c{|a, b| a.value == b})] do |v|
20
+ assert Success.new
21
+ end
22
+ end
23
+
24
+ def rules_that_share_a_function
25
+ func = c{|a, b| a.times += 1; b == "foobar"}
26
+
27
+ rule [FuncFact, :a, m.value > 1, f("foobar", func)] do |v|
28
+ assert Success.new
29
+ end
30
+
31
+ rule [FuncFact, :a, m.value > 2, f("foobar", func)] do |v|
32
+ assert Success.new
33
+ end
34
+ end
35
+
36
+ def rules_with_many_args_function
37
+ rule [FuncFact, :a, f([1, 2, 3, 4], c{|a, b, c, d, e| b < e})] do |v|
38
+ assert Success.new
39
+ end
40
+ end
41
+
42
+ def rules_with_no_args_function
43
+ rule [FuncFact, :a, f(c{|a| !a.nil?})] do |v|
44
+ assert Success.new
45
+ end
46
+ end
47
+ end
48
+
49
+ describe Ruleby::Rulebook do
50
+
51
+ describe "#f" do
52
+ context "rules_with_simple_function" do
53
+ subject do
54
+ engine :engine do |e|
55
+ FunctionsRulebook.new(e).rules_with_simple_function
56
+ end
57
+ end
58
+
59
+ context "with one FuncFact" do
60
+ before do
61
+ subject.assert FuncFact.new
62
+ subject.match
63
+ end
64
+
65
+ it "should match once" do
66
+ r = subject.retrieve Success
67
+ r.size.should == 1
68
+ subject.errors.should == []
69
+ end
70
+ end
71
+ end
72
+
73
+ context "rules_with_function_testing_self(:foo)" do
74
+ subject do
75
+ engine :engine do |e|
76
+ FunctionsRulebook.new(e).rules_with_function_testing_self(:foo)
77
+ end
78
+ end
79
+
80
+ context "with one FuncFact" do
81
+ before do
82
+ subject.assert FuncFact.new(:foo)
83
+ subject.match
84
+ end
85
+
86
+ it "should match once" do
87
+ r = subject.retrieve Success
88
+ r.size.should == 1
89
+ subject.errors.should == []
90
+ end
91
+ end
92
+ end
93
+
94
+ context "rules_with_function_testing_self(:bar)" do
95
+ subject do
96
+ engine :engine do |e|
97
+ FunctionsRulebook.new(e).rules_with_function_testing_self(:bar)
98
+ end
99
+ end
100
+
101
+ context "with one FuncFact" do
102
+ before do
103
+ subject.assert FuncFact.new(:foo)
104
+ subject.match
105
+ end
106
+
107
+ it "should not match " do
108
+ r = subject.retrieve Success
109
+ r.size.should == 0
110
+ subject.errors.should == []
111
+ end
112
+ end
113
+ end
114
+
115
+ context "rules_that_share_a_function" do
116
+ subject do
117
+ engine :engine do |e|
118
+ FunctionsRulebook.new(e).rules_that_share_a_function
119
+ end
120
+ end
121
+
122
+ context "with one FuncFact" do
123
+ before do
124
+ @f = FuncFact.new(3)
125
+ subject.assert @f
126
+ subject.match
127
+ end
128
+
129
+ it "should match, node should be shared, function should be evaled once" do
130
+ r = subject.retrieve Success
131
+ r.size.should == 2
132
+ subject.errors.should == []
133
+
134
+ @f.times.should == 1
135
+
136
+ subject.retract r[0]
137
+ subject.retract r[1]
138
+ subject.retract @f
139
+ subject.match
140
+
141
+ r = subject.retrieve Success
142
+ r.size.should == 0
143
+ subject.errors.should == []
144
+
145
+ subject.assert @f
146
+ subject.match
147
+
148
+ r = subject.retrieve Success
149
+ r.size.should == 2
150
+ subject.errors.should == []
151
+
152
+ @f.times.should == 2
153
+ end
154
+ end
155
+ end
156
+
157
+ context "rules_with_many_args_function" do
158
+ subject do
159
+ engine :engine do |e|
160
+ FunctionsRulebook.new(e).rules_with_many_args_function
161
+ end
162
+ end
163
+
164
+ context "with one FuncFact" do
165
+ before do
166
+ subject.assert FuncFact.new
167
+ subject.match
168
+ end
169
+
170
+ it "should match once" do
171
+ r = subject.retrieve Success
172
+ r.size.should == 1
173
+ subject.errors.should == []
174
+ end
175
+ end
176
+ end
177
+
178
+ context "rules_with_no_args_function" do
179
+ subject do
180
+ engine :engine do |e|
181
+ FunctionsRulebook.new(e).rules_with_no_args_function
182
+ end
183
+ end
184
+
185
+ context "with one FuncFact" do
186
+ before do
187
+ subject.assert FuncFact.new
188
+ subject.match
189
+ end
190
+
191
+ it "should match once" do
192
+ r = subject.retrieve Success
193
+ r.size.should == 1
194
+ subject.errors.should == []
195
+ end
196
+ end
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ class HelloFact
4
+ attr :value, true
5
+ def initialize(v=nil); @value = v; end
6
+ end
7
+
8
+ include Ruleby
9
+
10
+ class HelloRulebook < Rulebook
11
+ def rules
12
+ rule [HelloFact, :h] do
13
+ assert Success.new
14
+ end
15
+ end
16
+ end
17
+
18
+ describe Ruleby::Core::Engine do
19
+ subject do
20
+ engine :engine do |e|
21
+ HelloRulebook.new(e).rules
22
+ end
23
+ end
24
+
25
+ before do
26
+ subject.assert HelloFact.new
27
+ subject.match
28
+ end
29
+
30
+ it "should have matched" do
31
+ subject.errors.should == []
32
+ subject.retrieve(Success).size.should == 1
33
+ end
34
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ class NodeShareFact
4
+ attr_reader :times
5
+
6
+ def initialize(v=nil); @value = v; @times = 0; end
7
+
8
+ def value
9
+ @times += 1
10
+ @value
11
+ end
12
+ end
13
+
14
+ include Ruleby
15
+
16
+ class NodeShareRulebook < Rulebook
17
+ def rules
18
+ rule [NodeShareFact, :n, m.value == 5] do
19
+ assert Success.new
20
+ end
21
+
22
+ rule [NodeShareFact, :n, m.value == 5] do
23
+ assert Success.new
24
+ end
25
+
26
+ rule [NodeShareFact, :n, m.value == 6] do
27
+ assert Success.new
28
+ end
29
+ end
30
+ end
31
+
32
+ describe Ruleby::Core::Engine do
33
+
34
+ describe "node sharing" do
35
+ subject do
36
+ engine :engine do |e|
37
+ NodeShareRulebook.new(e).rules
38
+ end
39
+ end
40
+
41
+ before do
42
+ @f = NodeShareFact.new(5)
43
+ subject.assert @f
44
+ subject.match
45
+ end
46
+
47
+ it "should have matched" do
48
+ @f.times.should == 1
49
+ subject.errors.should == []
50
+ subject.retrieve(Success).size.should == 2
51
+ end
52
+ end
53
+ end