ruler 1.0.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/bin/example.rb +1 -1
- data/lib/ruler.rb +23 -8
- data/spec/ruler_spec.rb +44 -0
- metadata +4 -4
data/Rakefile
CHANGED
@@ -16,7 +16,7 @@ Jeweler::Tasks.new do |gem|
|
|
16
16
|
gem.homepage = "http://github.com/BlueFrogGaming/ruler"
|
17
17
|
gem.license = "MIT"
|
18
18
|
gem.summary = %Q{Ruby DSL to help with rules and facts}
|
19
|
-
gem.description = %Q{
|
19
|
+
gem.description = %Q{Ruler module implements a DSL that makes it easy to write a set of facts and rules. If you have some tricky conditional logic, Ruler can help clear it up.}
|
20
20
|
gem.email = "kognate@gmail.com"
|
21
21
|
gem.authors = ["Joshua Smith"]
|
22
22
|
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.2.0
|
data/bin/example.rb
CHANGED
data/lib/ruler.rb
CHANGED
@@ -8,7 +8,13 @@
|
|
8
8
|
# Copyright:: (c) 2011 Blue Frog Gaming, All Rights Reserved
|
9
9
|
# License:: This file has no public license.
|
10
10
|
|
11
|
-
class
|
11
|
+
class RulerError < StandardError
|
12
|
+
end
|
13
|
+
|
14
|
+
class BadDefaultRule < RulerError
|
15
|
+
end
|
16
|
+
|
17
|
+
class BadNotCall < RulerError
|
12
18
|
end
|
13
19
|
|
14
20
|
module Ruler
|
@@ -73,19 +79,28 @@ module Ruler
|
|
73
79
|
# will never be used.
|
74
80
|
def fact name, dval = nil, &blk
|
75
81
|
if dval.nil?
|
76
|
-
Thread.current[:working_memory][name] = yield
|
82
|
+
Thread.current[:working_memory][name] = {:value => yield }
|
77
83
|
else
|
78
|
-
Thread.current[:working_memory][name] = dval
|
84
|
+
Thread.current[:working_memory][name] = {:value => dval }
|
79
85
|
end
|
80
86
|
end
|
81
87
|
|
88
|
+
# a dynamic_fact is evaulated every time the fact is checked. Unlike a normal fact, which
|
89
|
+
# is only evaluated once, dynamic facts are evaluated once for each rule they appear in
|
90
|
+
def dynamic_fact name, &blk
|
91
|
+
Thread.current[:working_memory][name] = {:transient => true, :block => blk }
|
92
|
+
end
|
82
93
|
|
83
|
-
# allows for a fact to be NOT another fact.
|
94
|
+
# allows for a fact to be NOT another fact. notf cannot be used with a dynamic_fact
|
84
95
|
# for example:
|
85
96
|
# fact :one, 10 == 10
|
86
97
|
# fact :notfone, not(:one)
|
87
98
|
def notf name
|
88
|
-
|
99
|
+
if Thread.current[:working_memory][name][:transient]
|
100
|
+
raise BadNotCall.new("Cannot call notf on dynamic fact")
|
101
|
+
else
|
102
|
+
not(Thread.current[:working_memory][name][:value])
|
103
|
+
end
|
89
104
|
end
|
90
105
|
|
91
106
|
# a rule takes a list of fact names and a block. Rules are evaluated in the order
|
@@ -101,7 +116,7 @@ module Ruler
|
|
101
116
|
# there is no check to see if fact names are valid, and facts can be (re)defined
|
102
117
|
#inside of rules. Fact names are false if they are not defined.
|
103
118
|
def rule vlist,docstr = nil,&blk
|
104
|
-
dbg = lambda {|va| puts "|=-\t#{va} = #{Thread.current[:working_memory][va]}" }
|
119
|
+
dbg = lambda {|va| puts Thread.current[:working_memory][va][:transient].nil? ? "|=-\t#{va} = #{Thread.current[:working_memory][va][:value]}" : "|=-\t#{va} = #{Thread.current[:working_memory][va][:block].call()}" }
|
105
120
|
if @DEBUG
|
106
121
|
puts "---------------------------------------"
|
107
122
|
puts vlist.join(" & ")
|
@@ -112,8 +127,8 @@ module Ruler
|
|
112
127
|
if Thread.current[:singletary] && Thread.current[:rulematched]
|
113
128
|
Thread.current[:rulematched]
|
114
129
|
else
|
115
|
-
|
116
|
-
Thread.current[:rulematched] = if vlist.inject(true) {|k,v| k ? k &&
|
130
|
+
conditional_call = lambda {|n| Thread.current[:working_memory][n][:transient].nil? ? Thread.current[:working_memory][n][:value] : Thread.current[:working_memory][n][:block].call() }
|
131
|
+
Thread.current[:rulematched] = if vlist.inject(true) {|k,v| k ? k && conditional_call.call(v) : false }
|
117
132
|
yield
|
118
133
|
end
|
119
134
|
end
|
data/spec/ruler_spec.rb
CHANGED
@@ -137,6 +137,39 @@ I think.
|
|
137
137
|
end
|
138
138
|
end
|
139
139
|
end
|
140
|
+
|
141
|
+
def test_ten
|
142
|
+
#@DEBUG = true
|
143
|
+
ruleset do
|
144
|
+
dynamic_fact :one do
|
145
|
+
self.checking_method
|
146
|
+
end
|
147
|
+
|
148
|
+
fact :wrong, false
|
149
|
+
|
150
|
+
rule [:one, :wrong] do
|
151
|
+
false
|
152
|
+
end
|
153
|
+
|
154
|
+
rule [:one, :one, :wrong] do
|
155
|
+
false
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_eleven
|
161
|
+
ruleset do
|
162
|
+
dynamic_fact :one do
|
163
|
+
true
|
164
|
+
end
|
165
|
+
|
166
|
+
fact :two, notf(:one)
|
167
|
+
|
168
|
+
default_rule do
|
169
|
+
true
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
140
173
|
end
|
141
174
|
|
142
175
|
describe Rules do
|
@@ -187,5 +220,16 @@ describe Rules do
|
|
187
220
|
lambda { r.test_nine.should}.should raise_error
|
188
221
|
end
|
189
222
|
|
223
|
+
it "should call dynamic rules each time they are evaluated" do
|
224
|
+
r = Rules.new
|
225
|
+
r.expects(:checking_method).times(3).returns(true)
|
226
|
+
r.test_ten.should be(nil)
|
227
|
+
end
|
228
|
+
|
229
|
+
it "should throw an exception if a dyanmic fact is declared in a notf" do
|
230
|
+
r = Rules.new
|
231
|
+
lambda { r.test_eleven }.should raise_error
|
232
|
+
end
|
233
|
+
|
190
234
|
end
|
191
235
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 31
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
+
- 2
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 1.0.0
|
10
|
+
version: 1.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Joshua Smith
|
@@ -94,7 +94,7 @@ dependencies:
|
|
94
94
|
name: mocha
|
95
95
|
requirement: *id005
|
96
96
|
type: :development
|
97
|
-
description:
|
97
|
+
description: Ruler module implements a DSL that makes it easy to write a set of facts and rules. If you have some tricky conditional logic, Ruler can help clear it up.
|
98
98
|
email: kognate@gmail.com
|
99
99
|
executables:
|
100
100
|
- example.rb
|