predicated 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/README.markdown +183 -1
  2. data/lib/predicated.rb +1 -3
  3. data/lib/predicated/constrain.rb +2 -0
  4. data/lib/predicated/evaluate.rb +25 -6
  5. data/lib/predicated/from/callable_object.rb +7 -8
  6. data/lib/predicated/from/json.rb +59 -0
  7. data/lib/predicated/from/{ruby_string.rb → ruby_code_string.rb} +13 -5
  8. data/lib/predicated/from/{url_fragment.rb → url_part.rb} +17 -10
  9. data/lib/predicated/from/xml.rb +61 -0
  10. data/lib/predicated/predicate.rb +62 -43
  11. data/lib/predicated/print.rb +28 -16
  12. data/lib/predicated/selectable.rb +102 -0
  13. data/lib/predicated/simple_templated_predicate.rb +79 -0
  14. data/lib/predicated/string_utils.rb +20 -0
  15. data/lib/predicated/to/arel.rb +28 -22
  16. data/lib/predicated/to/json.rb +48 -0
  17. data/lib/predicated/to/sentence.rb +17 -14
  18. data/lib/predicated/to/solr.rb +15 -0
  19. data/lib/predicated/to/xml.rb +67 -0
  20. data/lib/predicated/version.rb +2 -2
  21. data/test/canonical_transform_cases.rb +67 -0
  22. data/test/constrain_test.rb +20 -11
  23. data/test/enumerable_test.rb +6 -34
  24. data/test/equality_test.rb +15 -4
  25. data/test/evaluate_test.rb +31 -26
  26. data/test/from/callable_object_canonical_test.rb +43 -0
  27. data/test/from/callable_object_test.rb +16 -40
  28. data/test/from/json_test.rb +83 -0
  29. data/test/from/ruby_code_string_canonical_test.rb +37 -0
  30. data/test/from/ruby_code_string_test.rb +103 -0
  31. data/test/from/{url_fragment_parser_test.rb → url_part_parser_test.rb} +20 -13
  32. data/test/from/url_part_test.rb +48 -0
  33. data/test/from/xml_test.rb +57 -0
  34. data/test/json_conversion_test.rb +33 -0
  35. data/test/print_test.rb +26 -25
  36. data/test/selectable_test.rb +123 -0
  37. data/test/simple_templated_predicate_test.rb +39 -0
  38. data/test/suite.rb +2 -4
  39. data/test/test_helper.rb +26 -4
  40. data/test/test_helper_with_wrong.rb +3 -2
  41. data/test/to/arel_test.rb +71 -31
  42. data/test/to/json_test.rb +74 -0
  43. data/test/to/sentence_test.rb +41 -34
  44. data/test/to/solr_test.rb +39 -0
  45. data/test/to/xml_test.rb +72 -0
  46. data/test/xml_conversion_test.rb +34 -0
  47. metadata +44 -16
  48. data/lib/predicated/selector.rb +0 -55
  49. data/test/from/ruby_string_test.rb +0 -135
  50. data/test/from/url_fragment_test.rb +0 -37
  51. data/test/selector_test.rb +0 -82
@@ -0,0 +1,34 @@
1
+ require "./test/test_helper_with_wrong"
2
+
3
+ require "predicated/from/xml"
4
+ require "predicated/to/xml"
5
+ include Predicated
6
+
7
+ regarding "convert xml back and forth" do
8
+
9
+ test "string to predicate to string" do
10
+ assert{ Predicate.from_xml("<equal><left>a</left><right>3</right></equal>").to_xml ==
11
+ "<equal><left>a</left><right>3</right></equal>" }
12
+
13
+ complex_xml = %{
14
+ <or>
15
+ <and>
16
+ <equal><left>a</left><right>1</right></equal>
17
+ <equal><left>b</left><right>2</right></equal>
18
+ </and>
19
+ <equal><left>c</left><right>3</right></equal>
20
+ </or>
21
+ }
22
+
23
+ assert{ Predicate.from_xml(complex_xml).to_xml.gsub(/\s/, "") ==
24
+ complex_xml.gsub(/\s/, "") }
25
+ end
26
+
27
+ test "predicate to string to predicate. note the loss of type fidelity." do
28
+ assert{ Predicate.from_xml(Predicate{ Eq("a",3) }.to_xml) == Predicate{ Eq("a",'3') } }
29
+
30
+ assert{ Predicate.from_xml(Predicate{ Or(And(Eq("a",1),Eq("b",2)), Eq("c",3)) }.to_xml) ==
31
+ Predicate{ Or(And(Eq("a",'1'),Eq("b",'2')), Eq("c",'3')) } }
32
+ end
33
+
34
+ end
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: predicated
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
5
4
  prerelease: false
6
5
  segments:
7
6
  - 0
8
- - 1
7
+ - 2
9
8
  - 0
10
- version: 0.1.0
9
+ version: 0.2.0
11
10
  platform: ruby
12
11
  authors:
13
12
  - Steve Conover
@@ -31,32 +30,50 @@ files:
31
30
  - lib/predicated/constrain.rb
32
31
  - lib/predicated/evaluate.rb
33
32
  - lib/predicated/from/callable_object.rb
34
- - lib/predicated/from/ruby_string.rb
35
- - lib/predicated/from/url_fragment.rb
33
+ - lib/predicated/from/json.rb
34
+ - lib/predicated/from/ruby_code_string.rb
35
+ - lib/predicated/from/url_part.rb
36
+ - lib/predicated/from/xml.rb
36
37
  - lib/predicated/gem_check.rb
37
38
  - lib/predicated/predicate.rb
38
39
  - lib/predicated/print.rb
39
- - lib/predicated/selector.rb
40
+ - lib/predicated/selectable.rb
41
+ - lib/predicated/simple_templated_predicate.rb
42
+ - lib/predicated/string_utils.rb
40
43
  - lib/predicated/to/arel.rb
44
+ - lib/predicated/to/json.rb
41
45
  - lib/predicated/to/sentence.rb
46
+ - lib/predicated/to/solr.rb
47
+ - lib/predicated/to/xml.rb
42
48
  - lib/predicated/version.rb
43
49
  - lib/predicated.rb
44
50
  - README.markdown
51
+ - test/canonical_transform_cases.rb
45
52
  - test/constrain_test.rb
46
53
  - test/enumerable_test.rb
47
54
  - test/equality_test.rb
48
55
  - test/evaluate_test.rb
56
+ - test/from/callable_object_canonical_test.rb
49
57
  - test/from/callable_object_test.rb
50
- - test/from/ruby_string_test.rb
51
- - test/from/url_fragment_parser_test.rb
52
- - test/from/url_fragment_test.rb
58
+ - test/from/json_test.rb
59
+ - test/from/ruby_code_string_canonical_test.rb
60
+ - test/from/ruby_code_string_test.rb
61
+ - test/from/url_part_parser_test.rb
62
+ - test/from/url_part_test.rb
63
+ - test/from/xml_test.rb
64
+ - test/json_conversion_test.rb
53
65
  - test/print_test.rb
54
- - test/selector_test.rb
66
+ - test/selectable_test.rb
67
+ - test/simple_templated_predicate_test.rb
55
68
  - test/suite.rb
56
69
  - test/test_helper.rb
57
70
  - test/test_helper_with_wrong.rb
58
71
  - test/to/arel_test.rb
72
+ - test/to/json_test.rb
59
73
  - test/to/sentence_test.rb
74
+ - test/to/solr_test.rb
75
+ - test/to/xml_test.rb
76
+ - test/xml_conversion_test.rb
60
77
  has_rdoc: true
61
78
  homepage: http://github.com/sconover/predicated
62
79
  licenses: []
@@ -71,7 +88,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
71
88
  requirements:
72
89
  - - ">="
73
90
  - !ruby/object:Gem::Version
74
- hash: 3
91
+ hash: 2382763030672668207
75
92
  segments:
76
93
  - 0
77
94
  version: "0"
@@ -80,7 +97,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
80
97
  requirements:
81
98
  - - ">="
82
99
  - !ruby/object:Gem::Version
83
- hash: 3
100
+ hash: 2382763030672668207
84
101
  segments:
85
102
  - 0
86
103
  version: "0"
@@ -92,18 +109,29 @@ signing_key:
92
109
  specification_version: 3
93
110
  summary: Predicated is a simple predicate model for Ruby
94
111
  test_files:
112
+ - test/canonical_transform_cases.rb
95
113
  - test/constrain_test.rb
96
114
  - test/enumerable_test.rb
97
115
  - test/equality_test.rb
98
116
  - test/evaluate_test.rb
117
+ - test/from/callable_object_canonical_test.rb
99
118
  - test/from/callable_object_test.rb
100
- - test/from/ruby_string_test.rb
101
- - test/from/url_fragment_parser_test.rb
102
- - test/from/url_fragment_test.rb
119
+ - test/from/json_test.rb
120
+ - test/from/ruby_code_string_canonical_test.rb
121
+ - test/from/ruby_code_string_test.rb
122
+ - test/from/url_part_parser_test.rb
123
+ - test/from/url_part_test.rb
124
+ - test/from/xml_test.rb
125
+ - test/json_conversion_test.rb
103
126
  - test/print_test.rb
104
- - test/selector_test.rb
127
+ - test/selectable_test.rb
128
+ - test/simple_templated_predicate_test.rb
105
129
  - test/suite.rb
106
130
  - test/test_helper.rb
107
131
  - test/test_helper_with_wrong.rb
108
132
  - test/to/arel_test.rb
133
+ - test/to/json_test.rb
109
134
  - test/to/sentence_test.rb
135
+ - test/to/solr_test.rb
136
+ - test/to/xml_test.rb
137
+ - test/xml_conversion_test.rb
@@ -1,55 +0,0 @@
1
- module Predicated
2
- module Selector
3
- #this is no doubt totally non-performant with all the extends, and
4
- #could probably be just done better / more elegantly
5
- #seek help.
6
-
7
- def self.SelectorEnumerable(key_to_selecting_proc)
8
- Module.new do
9
- @key_to_selecting_proc = key_to_selecting_proc
10
-
11
- def self.extended(base)
12
- sym = "@key_to_selecting_proc".to_sym
13
- hash = base.instance_variable_get(sym) || {}
14
- base.instance_variable_set(sym, hash.merge(@key_to_selecting_proc))
15
- end
16
-
17
- def self.included(base)
18
- extended(base)
19
- end
20
-
21
- #ugh ugh
22
- def key_to_selecting_proc
23
- @key_to_selecting_proc || self.class.instance_variable_get("@key_to_selecting_proc".to_sym)
24
- end
25
-
26
- def select(*keys, &block)
27
- key = keys.shift if keys.length>=1
28
- result =
29
- if key
30
- selecting_proc = key_to_selecting_proc[key]
31
- raise "no selector found for '#{key}'. current selectors: [#{key_to_selecting_proc.collect{|k,v|k.to_s}.join(",")}]" unless selecting_proc
32
- memos_for(:select)[key] ||= super(&selecting_proc)
33
- else
34
- super(&block)
35
- end
36
- #ugh
37
- result.extend(Predicated::Selector.SelectorEnumerable(key_to_selecting_proc))
38
- keys.length>=1 ? result.select(*keys, &block) : result
39
- end
40
-
41
- private
42
- def memos_for(group)
43
- @memos ||= {}
44
- @memos[group] ||= {}
45
- end
46
- end
47
- end
48
-
49
- #ugh
50
- def SelectorEnumerable(key_to_selecting_proc)
51
- Predicated::Selector.SelectorEnumerable(key_to_selecting_proc)
52
- end
53
-
54
- end
55
- end
@@ -1,135 +0,0 @@
1
- require "test/test_helper"
2
-
3
- require "predicated/from/ruby_string"
4
- include Predicated
5
-
6
- apropos "parse a ruby predicate string" do
7
-
8
- apropos "basic operations" do
9
-
10
- #'Wrong'-style asserts are specifically avoided here.
11
- #the circularity between the two projects will make you crazy if you're not careful
12
-
13
- test "simple signs" do
14
- assert_equal Predicate.from_ruby_string("1==1"), Predicate{ Eq(1,1) }
15
- assert_equal Predicate.from_ruby_string(" 1 == 1 "), Predicate{ Eq(1,1) }
16
- assert_equal Predicate.from_ruby_string("0<1"), Predicate{ Lt(0,1) }
17
- assert_equal Predicate.from_ruby_string("2>1"), Predicate{ Gt(2,1) }
18
- assert_equal Predicate.from_ruby_string("1<=1"), Predicate{ Lte(1,1) }
19
- assert_equal Predicate.from_ruby_string("1>=1"), Predicate{ Gte(1,1) }
20
- end
21
-
22
- test "primitive types" do
23
- assert_equal Predicate.from_ruby_string("false==true"), Predicate{ Eq(false,true) }
24
- assert_equal Predicate.from_ruby_string("'yyy'=='zzz'"), Predicate{ Eq("yyy","zzz") }
25
- end
26
-
27
- test "simple and + or" do
28
- assert_equal Predicate.from_ruby_string("1==1 && 2==2"), Predicate{ And(Eq(1,1),Eq(2,2)) }
29
- assert_equal Predicate.from_ruby_string("1==1 and 2==2"), Predicate{ And(Eq(1,1),Eq(2,2)) }
30
- assert_equal Predicate.from_ruby_string("1==1 || 2==2"), Predicate{ Or(Eq(1,1),Eq(2,2)) }
31
- end
32
-
33
- class Color
34
- attr_reader :name
35
- def initialize(name)
36
- @name = name
37
- end
38
-
39
- def ==(other)
40
- other.is_a?(Color) && @name == other.name
41
- end
42
- end
43
-
44
- test "substitute in from the binding" do
45
- a = 1
46
- b = "1"
47
- c = "c"
48
- d = Color.new("purple")
49
-
50
- assert_equal Predicate.from_ruby_string("a==1", binding()), Predicate{ Eq(1,1) }
51
- assert_equal Predicate.from_ruby_string("b==1", binding()), Predicate{ Eq("1",1) }
52
- assert_equal Predicate.from_ruby_string("c==b", binding()), Predicate{ Eq("c","1") }
53
- assert_equal Predicate.from_ruby_string("d==d", binding()), Predicate{ Eq(Color.new("purple"),
54
- Color.new("purple")) }
55
- assert_equal Predicate.from_ruby_string("d==d", binding()).left, d
56
-
57
- assert_equal Predicate.from_ruby_string("a==b && b==c", binding()),
58
- Predicate{ And(Eq(1,"1"),Eq("1","c")) }
59
- end
60
-
61
-
62
- test "complex and + or" do
63
- assert_equal Predicate.from_ruby_string("1==1 && 2==2 || 3==3"),
64
- Predicate{ Or( And(Eq(1,1),Eq(2,2)), Eq(3,3) ) }
65
- end
66
-
67
- test "parens change precedence" do
68
- assert_equal Predicate.from_ruby_string("1==1 || 2==2 && 3==3"),
69
- Predicate{ Or( Eq(1,1), And(Eq(2,2),Eq(3,3)) ) }
70
-
71
- assert_equal Predicate.from_ruby_string("(1==1 || 2==2) && 3==3"),
72
- Predicate{ And( Or(Eq(1,1),Eq(2,2)), Eq(3,3) ) }
73
- end
74
-
75
- apropos "only pay attention to the final line" do
76
- #might hate myself one day for this. but what else does it make sense to do?
77
-
78
- test "simple" do
79
- assert_equal Predicate.from_ruby_string("z=2\nb=5\n1==1"), Predicate{ Eq(1,1) }
80
- end
81
-
82
- test "can make use of variables defined earlier in the block" do
83
- #might hate myself one day for this. but what else does it make sense to do?
84
- assert_equal Predicate.from_ruby_string("z=2\nb=5\nz==1"), Predicate{ Eq(2,1) }
85
- end
86
- end
87
-
88
- test "a call that returns a boolean result" do
89
- assert_equal Predicate.from_ruby_string("'abc'.include?('bc')"),
90
- Predicate{ Call("abc", :include?, "bc") }
91
-
92
- color = Color.new("purple")
93
- assert_equal Predicate.from_ruby_string("color.name.include?('rp')", binding()),
94
- Predicate{ Call("purple", :include?, "rp") }
95
-
96
- assert_equal Predicate.from_ruby_string("'abc'.nil?"),
97
- Predicate{ Call("abc", :nil?, nil) }
98
- end
99
-
100
- test "use of instance variables" do
101
- @a = 1
102
-
103
- assert_equal Predicate.from_ruby_string("@a==1", binding()), Predicate{ Eq(1,1) }
104
- end
105
-
106
- test "use of inline assignments" do
107
- assert_equal Predicate.from_ruby_string("(a=2)==1 && a==1"),
108
- Predicate{ And(Eq(2,1), Eq(2,1)) }
109
- end
110
-
111
- test "use of inline expressions" do
112
- assert_equal Predicate.from_ruby_string("(2*1)==1"),
113
- Predicate{ Eq(2,1) }
114
-
115
- assert_equal Predicate.from_ruby_string("[2,1].first==1"),
116
- Predicate{ Eq(2,1) }
117
- end
118
-
119
-
120
- end
121
-
122
- apropos "errors" do
123
- test "can't parse" do
124
- assert_raises(Racc::ParseError) do
125
- Predicate.from_ruby_string("bad ruby @@@@@****()(((")
126
- end
127
- end
128
-
129
- test "predicates only" do
130
- assert_raises(Predicated::Predicate::DontKnowWhatToDoWithThisSexpError) do
131
- Predicate.from_ruby_string("a=1")
132
- end
133
- end
134
- end
135
- end
@@ -1,37 +0,0 @@
1
- require "test/test_helper_with_wrong"
2
-
3
- require "predicated/from/url_fragment"
4
- include Predicated
5
-
6
- apropos "parse url fragments and convert them into predicates" do
7
-
8
- apropos "basic operations" do
9
-
10
- test "simple signs" do
11
- assert { Predicate.from_url_fragment("a=1") == Predicate{ Eq("a","1") } }
12
- assert { Predicate.from_url_fragment("a<1") == Predicate{ Lt("a","1") } }
13
- assert { Predicate.from_url_fragment("a>1") == Predicate{ Gt("a","1") } }
14
- assert { Predicate.from_url_fragment("a<=1") == Predicate{ Lte("a","1") } }
15
- assert { Predicate.from_url_fragment("a>=1") == Predicate{ Gte("a","1") } }
16
- end
17
-
18
- test "simple and + or" do
19
- assert { Predicate.from_url_fragment("a=1&b=2") == Predicate{ And(Eq("a","1"),Eq("b","2")) } }
20
- assert { Predicate.from_url_fragment("a=1|b=2") == Predicate{ Or(Eq("a","1"),Eq("b","2")) } }
21
- end
22
-
23
- test "complex and + or" do
24
- assert { Predicate.from_url_fragment("a=1&b=2|c=3") ==
25
- Predicate{ Or( And(Eq("a","1"),Eq("b","2")), Eq("c","3") ) } }
26
- end
27
-
28
- test "parens change precedence" do
29
- assert { Predicate.from_url_fragment("a=1|b=2&c=3") ==
30
- Predicate{ Or( Eq("a","1"), And(Eq("b","2"),Eq("c","3")) ) } }
31
-
32
- assert { Predicate.from_url_fragment("(a=1|b=2)&c=3") ==
33
- Predicate{ And( Or(Eq("a","1"),Eq("b","2")), Eq("c","3") ) } }
34
- end
35
-
36
- end
37
- end
@@ -1,82 +0,0 @@
1
- require "test/test_helper_with_wrong"
2
-
3
- require "predicated/selector"
4
- include Predicated::Selector
5
-
6
- apropos "part one: selectors on an array (simple enumerable). proving them out more generally." do
7
- before do
8
- @arr = [1,2,"c",4,"e",6]
9
- @arr.extend SelectorEnumerable(
10
- :strings => proc{|item|item.is_a?(String)},
11
- :numbers => proc{|item|item.is_a?(Numeric)},
12
- :less_than_3 => proc{|item|item < 3}
13
- )
14
- end
15
-
16
- test %{selection basics.
17
- People often remark that this kind of thing is jQuery-like.
18
- I keep thinking I got it from Eric Evans.} do
19
- assert{ @arr.select(:strings) == ["c","e"] }
20
- assert{ @arr.select(:numbers) == [1,2,4,6] }
21
- assert{ @arr.select(:numbers).select(:less_than_3) == [1,2] }
22
-
23
- assert do
24
- catch_raise{@arr.select(:less_than_3)}.is_a?(ArgumentError)
25
- #because strings don't respond to <
26
- #...there's no substitute for knowing what you're doing.
27
- end
28
-
29
- #normal select still works
30
- assert{ @arr.select{|item|item.is_a?(String)} == ["c","e"] }
31
- end
32
-
33
- test "...selector name can be any object" do
34
- arr = [1,2,"c",4,"e",6]
35
- arr.extend SelectorEnumerable(
36
- String => proc{|item|item.is_a?(String)},
37
- Numeric => proc{|item|item.is_a?(Numeric)},
38
- :less_than_3 => proc{|item|item < 3}
39
- )
40
-
41
- assert{ arr.select(String) == ["c","e"] }
42
- assert{ arr.select(Numeric) == [1,2,4,6] }
43
- assert{ arr.select(Numeric).select(:less_than_3) == [1,2] }
44
- end
45
-
46
- test "chaining. also works using varargs" do
47
- assert{ @arr.select(:numbers).select(:less_than_3) == [1,2] }
48
- assert{ @arr.select(:numbers, :less_than_3) == [1,2] }
49
- end
50
-
51
- test "extending twice is additive (not destructive)" do
52
- arr = [1,2,"c",4,"e",6]
53
- arr.extend SelectorEnumerable(:strings => proc{|item|item.is_a?(String)})
54
- arr.extend SelectorEnumerable(:numbers => proc{|item|item.is_a?(Numeric)})
55
-
56
- assert{ arr.select(:strings) == ["c","e"] }
57
- assert{ arr.select(:numbers) == [1,2,4,6] }
58
- end
59
-
60
- test "works as an include" do
61
- class MyArray < Array
62
- include SelectorEnumerable(:strings => proc{|item|item.is_a?(String)})
63
- include SelectorEnumerable(:numbers => proc{|item|item.is_a?(Numeric)})
64
- end
65
- arr = MyArray.new
66
- arr.replace([1,2,"c",4,"e",6])
67
-
68
- assert{ arr.select(:strings) == ["c","e"] }
69
- assert{ arr.select(:numbers) == [1,2,4,6] }
70
- end
71
-
72
- test %{memoizes.
73
- Selector enumerable assumes an immutable collection.
74
- I'm going to use that assumption against it, and cleverly prove that memoization works.
75
- (Others might choose to mock in similar circumstances.)} do
76
- assert{ @arr.select(:strings) == ["c","e"] }
77
-
78
- @arr << "zzz"
79
-
80
- assert{ @arr.select(:strings) == ["c","e"] }
81
- end
82
- end