predicated 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +183 -1
- data/lib/predicated.rb +1 -3
- data/lib/predicated/constrain.rb +2 -0
- data/lib/predicated/evaluate.rb +25 -6
- data/lib/predicated/from/callable_object.rb +7 -8
- data/lib/predicated/from/json.rb +59 -0
- data/lib/predicated/from/{ruby_string.rb → ruby_code_string.rb} +13 -5
- data/lib/predicated/from/{url_fragment.rb → url_part.rb} +17 -10
- data/lib/predicated/from/xml.rb +61 -0
- data/lib/predicated/predicate.rb +62 -43
- data/lib/predicated/print.rb +28 -16
- data/lib/predicated/selectable.rb +102 -0
- data/lib/predicated/simple_templated_predicate.rb +79 -0
- data/lib/predicated/string_utils.rb +20 -0
- data/lib/predicated/to/arel.rb +28 -22
- data/lib/predicated/to/json.rb +48 -0
- data/lib/predicated/to/sentence.rb +17 -14
- data/lib/predicated/to/solr.rb +15 -0
- data/lib/predicated/to/xml.rb +67 -0
- data/lib/predicated/version.rb +2 -2
- data/test/canonical_transform_cases.rb +67 -0
- data/test/constrain_test.rb +20 -11
- data/test/enumerable_test.rb +6 -34
- data/test/equality_test.rb +15 -4
- data/test/evaluate_test.rb +31 -26
- data/test/from/callable_object_canonical_test.rb +43 -0
- data/test/from/callable_object_test.rb +16 -40
- data/test/from/json_test.rb +83 -0
- data/test/from/ruby_code_string_canonical_test.rb +37 -0
- data/test/from/ruby_code_string_test.rb +103 -0
- data/test/from/{url_fragment_parser_test.rb → url_part_parser_test.rb} +20 -13
- data/test/from/url_part_test.rb +48 -0
- data/test/from/xml_test.rb +57 -0
- data/test/json_conversion_test.rb +33 -0
- data/test/print_test.rb +26 -25
- data/test/selectable_test.rb +123 -0
- data/test/simple_templated_predicate_test.rb +39 -0
- data/test/suite.rb +2 -4
- data/test/test_helper.rb +26 -4
- data/test/test_helper_with_wrong.rb +3 -2
- data/test/to/arel_test.rb +71 -31
- data/test/to/json_test.rb +74 -0
- data/test/to/sentence_test.rb +41 -34
- data/test/to/solr_test.rb +39 -0
- data/test/to/xml_test.rb +72 -0
- data/test/xml_conversion_test.rb +34 -0
- metadata +44 -16
- data/lib/predicated/selector.rb +0 -55
- data/test/from/ruby_string_test.rb +0 -135
- data/test/from/url_fragment_test.rb +0 -37
- data/test/selector_test.rb +0 -82
data/lib/predicated/to/arel.rb
CHANGED
@@ -6,30 +6,36 @@ module Predicated
|
|
6
6
|
|
7
7
|
require_gem_version("arel", "0.4.0")
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
def to_arel
|
14
|
-
#{arel_class.name}.new(left.to_arel, right.to_arel)
|
15
|
-
end
|
16
|
-
}
|
17
|
-
|
18
|
-
|
9
|
+
class And
|
10
|
+
def to_arel(arel_table)
|
11
|
+
Arel::Predicates::And.new(left.to_arel(arel_table), right.to_arel(arel_table))
|
12
|
+
end
|
19
13
|
end
|
20
14
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
}
|
32
|
-
|
15
|
+
class Or
|
16
|
+
def to_arel(arel_table)
|
17
|
+
Arel::Predicates::Or.new(left.to_arel(arel_table), right.to_arel(arel_table))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Not
|
22
|
+
def to_arel(arel_table)
|
23
|
+
Arel::Predicates::Not.new(inner.to_arel(arel_table))
|
24
|
+
end
|
33
25
|
end
|
34
26
|
|
27
|
+
|
28
|
+
class Operation
|
29
|
+
def to_arel(arel_table)
|
30
|
+
arel_class.new(arel_table.attributes[left], right)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Equal; def arel_class; Arel::Predicates::Equality end end
|
35
|
+
class LessThan; def arel_class; Arel::Predicates::LessThan end end
|
36
|
+
class GreaterThan; def arel_class; Arel::Predicates::GreaterThan end end
|
37
|
+
class LessThanOrEqualTo; def arel_class; Arel::Predicates::LessThanOrEqualTo end end
|
38
|
+
class GreaterThanOrEqualTo; def arel_class; Arel::Predicates::GreaterThanOrEqualTo end end
|
39
|
+
|
40
|
+
|
35
41
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "predicated/predicate"
|
2
|
+
|
3
|
+
module Predicated
|
4
|
+
|
5
|
+
require_gem_version("json", "1.1.9")
|
6
|
+
|
7
|
+
module JsonStructToJsonStr
|
8
|
+
def to_json_str
|
9
|
+
JSON.pretty_generate(to_json_struct)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class And
|
14
|
+
include JsonStructToJsonStr
|
15
|
+
def to_json_struct
|
16
|
+
{"and" => [left.to_json_struct, right.to_json_struct]}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Or
|
21
|
+
include JsonStructToJsonStr
|
22
|
+
def to_json_struct
|
23
|
+
{"or" => [left.to_json_struct, right.to_json_struct]}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Not
|
28
|
+
include JsonStructToJsonStr
|
29
|
+
def to_json_struct
|
30
|
+
{"not" => inner.to_json_struct}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Operation
|
35
|
+
include JsonStructToJsonStr
|
36
|
+
def to_json_struct
|
37
|
+
[left, json_sign, right]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class Equal; private; def json_sign; "==" end end
|
42
|
+
class LessThan; private; def json_sign; "<" end end
|
43
|
+
class GreaterThan; private; def json_sign; ">" end end
|
44
|
+
class LessThanOrEqualTo; private; def json_sign; "<=" end end
|
45
|
+
class GreaterThanOrEqualTo; private; def json_sign; ">=" end end
|
46
|
+
|
47
|
+
|
48
|
+
end
|
@@ -3,18 +3,28 @@ require "predicated/evaluate"
|
|
3
3
|
|
4
4
|
module Predicated
|
5
5
|
|
6
|
-
module
|
6
|
+
module Conjunction
|
7
7
|
def to_sentence
|
8
|
-
left.to_sentence +
|
8
|
+
left.to_sentence + joining_str + right.to_sentence
|
9
9
|
end
|
10
10
|
|
11
11
|
def to_negative_sentence
|
12
12
|
"This is not true: " + to_sentence
|
13
13
|
end
|
14
14
|
end
|
15
|
+
|
16
|
+
class And; include Conjunction; def joining_str; " and " end; end
|
17
|
+
class Or; include Conjunction; def joining_str; " or " end;end
|
15
18
|
|
16
|
-
class
|
17
|
-
|
19
|
+
class Not
|
20
|
+
def to_sentence
|
21
|
+
inner.to_negative_sentence
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_negative_sentence
|
25
|
+
inner.to_sentence
|
26
|
+
end
|
27
|
+
end
|
18
28
|
|
19
29
|
class Operation
|
20
30
|
|
@@ -76,16 +86,9 @@ module Predicated
|
|
76
86
|
end
|
77
87
|
|
78
88
|
def format_value(value)
|
79
|
-
|
80
|
-
"'" + value.to_s + "'"
|
81
|
-
elsif value.nil?
|
82
|
-
"nil"
|
83
|
-
elsif value.is_a?(Numeric) || value.is_a?(TrueClass) || value.is_a?(FalseClass)
|
84
|
-
value.to_s
|
85
|
-
else
|
86
|
-
"'" + value.inspect + "'"
|
87
|
-
end
|
89
|
+
value.inspect
|
88
90
|
end
|
91
|
+
|
89
92
|
end
|
90
93
|
|
91
|
-
end
|
94
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "predicated/predicate"
|
2
|
+
|
3
|
+
module Predicated
|
4
|
+
|
5
|
+
class And; def to_solr; "(#{left.to_solr} AND #{right.to_solr})" end end
|
6
|
+
class Or; def to_solr; "(#{left.to_solr} OR #{right.to_solr})" end end
|
7
|
+
class Not; def to_solr; "NOT(#{inner.to_solr})" end end
|
8
|
+
|
9
|
+
class Equal; def to_solr; "#{left}:#{right}" end end
|
10
|
+
class GreaterThan; def to_solr; "#{left}:[#{(right+1)} TO *]" end end
|
11
|
+
class LessThan; def to_solr; "#{left}:[* TO #{(right-1)}]" end end
|
12
|
+
class GreaterThanOrEqualTo; def to_solr; "#{left}:[#{right} TO *]" end end
|
13
|
+
class LessThanOrEqualTo; def to_solr; "#{left}:[* TO #{right}]" end end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require "predicated/predicate"
|
2
|
+
|
3
|
+
module Predicated
|
4
|
+
|
5
|
+
module ContainerToXml
|
6
|
+
private
|
7
|
+
def to_xml_with_tag_name(indent, tag_name)
|
8
|
+
inner = %{\n#{left.to_xml(indent + " ")}\n#{right.to_xml(indent + " ")}}
|
9
|
+
"#{indent}<#{tag_name}>#{inner}\n#{indent}</#{tag_name}>"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class And
|
14
|
+
include ContainerToXml
|
15
|
+
def to_xml(indent="")
|
16
|
+
to_xml_with_tag_name(indent, "and")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Or
|
21
|
+
include ContainerToXml
|
22
|
+
def to_xml(indent="")
|
23
|
+
to_xml_with_tag_name(indent, "or")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Not
|
28
|
+
def to_xml(indent="")
|
29
|
+
"#{indent}<not>\n#{inner.to_xml(indent + " ")}\n#{indent}</not>"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Operation
|
34
|
+
def to_xml(indent="")
|
35
|
+
"#{indent}<#{tag_name}><left>#{escape(left)}</left><right>#{escape(right)}</right></#{tag_name}>"
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
CONVERSION_TABLE = [
|
41
|
+
['&', '&'],
|
42
|
+
['<', '<'],
|
43
|
+
['>', '>'],
|
44
|
+
["'", '''],
|
45
|
+
['"', '"']
|
46
|
+
]
|
47
|
+
|
48
|
+
#it's fast. see http://groups.google.com/group/ruby-talk-google/browse_thread/thread/c0280bab8a037184/9b8ca81c2607189d?hl=en&ie=UTF-8
|
49
|
+
def escape(value)
|
50
|
+
if value.class == String
|
51
|
+
value.gsub(/['"&<>]/) do |match|
|
52
|
+
CONVERSION_TABLE.assoc(match).last
|
53
|
+
end
|
54
|
+
else
|
55
|
+
value
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class Equal; private; def tag_name; "equal" end end
|
61
|
+
class LessThan; private; def tag_name; "lessThan" end end
|
62
|
+
class GreaterThan; private; def tag_name; "greaterThan" end end
|
63
|
+
class LessThanOrEqualTo; private; def tag_name; "lessThanOrEqualTo" end end
|
64
|
+
class GreaterThanOrEqualTo; private; def tag_name; "greaterThanOrEqualTo" end end
|
65
|
+
|
66
|
+
|
67
|
+
end
|
data/lib/predicated/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
module Predicated
|
2
|
-
VERSION = "0.
|
3
|
-
end
|
2
|
+
VERSION = "0.2.0" unless defined?(Predicated::VERSION)
|
3
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module CanonicalTransformCases
|
2
|
+
|
3
|
+
module ClassMethods
|
4
|
+
def create_canonical_tests(expectations, proper_typing=true)
|
5
|
+
val = {
|
6
|
+
:one => 1,
|
7
|
+
:two => 2,
|
8
|
+
:three => 3,
|
9
|
+
:true_value => true,
|
10
|
+
:false_value => false
|
11
|
+
}
|
12
|
+
|
13
|
+
val.each{|k,v|val[k]=v.to_s} unless proper_typing
|
14
|
+
|
15
|
+
tests = {
|
16
|
+
"simple operations" => {
|
17
|
+
"eq" => Predicate{ Eq("a",val[:three]) },
|
18
|
+
"gt" => Predicate{ Gt("a",val[:three]) },
|
19
|
+
"lt" => Predicate{ Lt("a",val[:three]) },
|
20
|
+
"gte" => Predicate{ Gte("a",val[:three]) },
|
21
|
+
"lte" => Predicate{ Lte("a",val[:three]) }
|
22
|
+
},
|
23
|
+
"primitive types" => {
|
24
|
+
"true" => Predicate{ Eq("a",val[:true_value]) },
|
25
|
+
"false" => Predicate{ Eq("a",val[:false_value]) },
|
26
|
+
"string" => Predicate{ Eq("a","yyy") },
|
27
|
+
},
|
28
|
+
"not" => {
|
29
|
+
"simple" => Predicate{ Not(Eq("a",val[:true_value])) }
|
30
|
+
},
|
31
|
+
"simple and / or" => {
|
32
|
+
"and" => Predicate{ And(Eq("a", val[:one]),Eq("b", val[:two])) },
|
33
|
+
"or" => Predicate{ Or(Eq("a", val[:one]),Eq("b", val[:two])) }
|
34
|
+
},
|
35
|
+
"complex and / or" => {
|
36
|
+
"or and" => Predicate{ Or(And(Eq("a", val[:one]),Eq("b", val[:two])), Eq("c",val[:three])) }
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
tests.each do |test_name, cases|
|
41
|
+
test test_name do
|
42
|
+
|
43
|
+
not_found =
|
44
|
+
cases.keys.sort.select do |case_name|
|
45
|
+
expectations[test_name].nil? ||
|
46
|
+
expectations[test_name][case_name].nil?
|
47
|
+
end
|
48
|
+
|
49
|
+
raise "no expectation defined for test: '#{test_name}' cases: [#{not_found.join(", ")}]" unless not_found.empty?
|
50
|
+
|
51
|
+
cases.each do |case_name, predicate|
|
52
|
+
actual = if block_given?
|
53
|
+
yield(predicate)
|
54
|
+
else
|
55
|
+
predicate
|
56
|
+
end
|
57
|
+
assert { actual == expectations[test_name][case_name] }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.included(other)
|
65
|
+
other.extend(ClassMethods)
|
66
|
+
end
|
67
|
+
end
|
data/test/constrain_test.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
require "test/test_helper_with_wrong"
|
1
|
+
require "./test/test_helper_with_wrong"
|
2
2
|
|
3
3
|
require "predicated/predicate"
|
4
4
|
require "predicated/constrain"
|
5
5
|
include Predicated
|
6
6
|
|
7
|
-
|
7
|
+
regarding %{constraints are rules about the content and structure of predicates.
|
8
8
|
a predicate might violate a constraint} do
|
9
9
|
|
10
10
|
before do
|
@@ -16,16 +16,25 @@ apropos %{constraints are rules about the content and structure of predicates.
|
|
16
16
|
@not_more_than_two_levels_deep =
|
17
17
|
Constraint.new(:name => "Limited to two levels deep",
|
18
18
|
:check_that => proc{|predicate, ancestors| ancestors.length<=2})
|
19
|
+
|
20
|
+
@one = Predicate{Eq(1,1)}
|
21
|
+
@two = Predicate{Eq(2,2)}
|
22
|
+
@three = Predicate{Eq(3,3)}
|
23
|
+
|
24
|
+
@one_and_three = Predicate{And(Eq(1,1), Eq(3,3))}
|
25
|
+
@one_and_two = Predicate{And(Eq(1,1), Eq(2,2))}
|
26
|
+
|
27
|
+
@deeply_nested = Predicate{Or(Or(And(Eq(1,1), Eq(3,3)), Eq(4,4)), Eq(5,5))}
|
19
28
|
end
|
20
29
|
|
21
30
|
test "apply to each predicate - simple" do
|
22
31
|
constraints = Constraints.new.add(@value_not_equal_to_two)
|
23
32
|
|
24
|
-
assert{ constraints.check(
|
25
|
-
deny { constraints.check(
|
33
|
+
assert{ constraints.check(@one).pass? }
|
34
|
+
deny { constraints.check(@two).pass? }
|
26
35
|
|
27
|
-
assert{ constraints.check(
|
28
|
-
deny { constraints.check(
|
36
|
+
assert{ constraints.check(@one_and_three).pass? }
|
37
|
+
deny { constraints.check(@one_and_two).pass? }
|
29
38
|
end
|
30
39
|
|
31
40
|
test "apply each to each predicate - many constraints" do
|
@@ -34,11 +43,11 @@ apropos %{constraints are rules about the content and structure of predicates.
|
|
34
43
|
add(@value_not_equal_to_two).
|
35
44
|
add(@not_more_than_two_levels_deep)
|
36
45
|
|
37
|
-
assert{ constraints.check(
|
38
|
-
deny { constraints.check(
|
46
|
+
assert{ constraints.check(@one_and_three).pass? }
|
47
|
+
deny { constraints.check(@one_and_two).pass? }
|
39
48
|
|
40
|
-
assert{ constraints.check(
|
41
|
-
deny { constraints.check(
|
49
|
+
assert{ constraints.check(@one_and_three).pass? }
|
50
|
+
deny { constraints.check(@deeply_nested).pass? }
|
42
51
|
end
|
43
52
|
|
44
53
|
test "equality" do
|
@@ -60,7 +69,7 @@ apropos %{constraints are rules about the content and structure of predicates.
|
|
60
69
|
along with the offending predicates} do
|
61
70
|
constraints = Constraints.new.add(@value_not_equal_to_two)
|
62
71
|
|
63
|
-
result = constraints.check(
|
72
|
+
result = constraints.check(@one)
|
64
73
|
assert{ result.pass? }
|
65
74
|
assert{ result.violations == {} }
|
66
75
|
|
data/test/enumerable_test.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
require "test/test_helper_with_wrong"
|
1
|
+
require "./test/test_helper_with_wrong"
|
2
2
|
|
3
3
|
require "predicated/predicate"
|
4
4
|
include Predicated
|
5
5
|
|
6
|
-
|
6
|
+
regarding "you can flip through the predicate tree, like any enumerable. a list of ancestors of each node are provided" do
|
7
7
|
|
8
8
|
test "simple" do
|
9
9
|
assert { Predicate { Eq(1, 2) }.to_a == [[Predicate { Eq(1, 2) }, []]] }
|
@@ -23,38 +23,10 @@ apropos "you can flip through the predicate tree, like any enumerable. a list o
|
|
23
23
|
}
|
24
24
|
end
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
class Array
|
30
|
-
def predicates
|
31
|
-
collect{|p, a|p}
|
32
|
-
end
|
26
|
+
test "not" do
|
27
|
+
the_top = Predicate { Not(Eq(1, 2)) }
|
28
|
+
assert { the_top.to_a == [[the_top, []], [Predicate { Eq(1, 2) }, [the_top]]] }
|
33
29
|
end
|
34
|
-
|
35
|
-
it "gets predicate parts by type" do
|
36
|
-
root = Predicate { And(Eq(1, 2), Or(Eq(3, 4), Eq(5, 6))) }
|
37
|
-
the_or = Predicate { Or(Eq(3, 4), Eq(5, 6)) }
|
38
|
-
|
39
|
-
assert{ root.select(:all).predicates == [root, Equal.new(1, 2), the_or, Equal.new(3, 4), Equal.new(5, 6)] }
|
40
30
|
|
41
|
-
|
42
|
-
assert{ root.select(Or).predicates == [the_or] }
|
43
|
-
assert{ root.select(Equal).predicates == [Equal.new(1, 2), Equal.new(3, 4), Equal.new(5, 6)] }
|
44
|
-
assert{ root.select(GreaterThan).predicates == [] }
|
45
|
-
|
46
|
-
gt_lt = Predicate { And(Gt(1, 2), Lt(3, 4)) }
|
47
|
-
assert{ gt_lt.select(GreaterThan).predicates == [GreaterThan.new(1, 2)] }
|
48
|
-
assert{ gt_lt.select(LessThan).predicates == [LessThan.new(3, 4)] }
|
31
|
+
end
|
49
32
|
|
50
|
-
gte_lte = Predicate { And(Gte(1, 2), Lte(3, 4)) }
|
51
|
-
assert{ gte_lte.select(GreaterThanOrEqualTo).predicates == [GreaterThanOrEqualTo.new(1, 2)] }
|
52
|
-
assert{ gte_lte.select(LessThanOrEqualTo).predicates == [LessThanOrEqualTo.new(3, 4)] }
|
53
|
-
|
54
|
-
mixed = Predicate { And(Eq(1, 2), Or(Gt(3, 4), Lt(5, 6))) }
|
55
|
-
mixed_or = Predicate { Or(Gt(3, 4), Lt(5, 6)) }
|
56
|
-
assert{ mixed.select(Operation).predicates == [Equal.new(1, 2), GreaterThan.new(3, 4), LessThan.new(5, 6)] }
|
57
|
-
assert{ mixed.select(Operation).select(Equal).predicates == [Equal.new(1, 2)] }
|
58
|
-
assert{ mixed.select(Binary).predicates == [mixed, Equal.new(1, 2), mixed_or, GreaterThan.new(3, 4), LessThan.new(5, 6)] }
|
59
|
-
end
|
60
|
-
end
|
data/test/equality_test.rb
CHANGED
@@ -1,21 +1,32 @@
|
|
1
|
-
require "test/test_helper_with_wrong"
|
1
|
+
require "./test/test_helper_with_wrong"
|
2
2
|
|
3
3
|
require "predicated/predicate"
|
4
4
|
include Predicated
|
5
5
|
|
6
|
-
|
6
|
+
regarding "prove value equality" do
|
7
7
|
|
8
8
|
test "simple" do
|
9
9
|
assert { Predicate { Eq(1, 1) } == Predicate { Eq(1, 1) } }
|
10
10
|
deny { Predicate { Eq(1, 1) } == Predicate { Eq(1, 99) } }
|
11
11
|
end
|
12
12
|
|
13
|
+
test "unary" do
|
14
|
+
assert { Predicate { Not(Eq(1, 1)) } == Predicate { Not(Eq(1, 1)) } }
|
15
|
+
deny { Predicate { Not(Eq(1, 1)) } == Predicate { Not(Eq(99, 99)) } }
|
16
|
+
end
|
17
|
+
|
13
18
|
test "complex" do
|
14
19
|
assert { Predicate { And(Eq(1, 1), Or(Eq(2, 2), Eq(3, 3))) } ==
|
15
20
|
Predicate { And(Eq(1, 1), Or(Eq(2, 2), Eq(3, 3))) } }
|
16
21
|
|
17
|
-
deny
|
22
|
+
deny { Predicate { And(Eq(1, 1), Or(Eq(2, 2), Eq(3, 3))) } ==
|
18
23
|
Predicate { And(Eq(1, 1), Or(Eq(2, 99), Eq(3, 3))) } }
|
19
24
|
end
|
20
25
|
|
21
|
-
end
|
26
|
+
end
|
27
|
+
|
28
|
+
regarding "predicate base class. not sure I'm happy with the implementation...too tricky" do
|
29
|
+
test "all predicates descend from a predicate base class. it's a marker class" do
|
30
|
+
assert{ And.new(Equal.new(1,1),Equal.new(2,2)).is_a?(Predicate) }
|
31
|
+
end
|
32
|
+
end
|