predicated 0.1.0 → 0.2.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.
- 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
|