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.
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