squeel 0.5.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 (72) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +8 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +41 -0
  5. data/Rakefile +19 -0
  6. data/lib/core_ext/hash.rb +13 -0
  7. data/lib/core_ext/symbol.rb +36 -0
  8. data/lib/squeel.rb +26 -0
  9. data/lib/squeel/adapters/active_record.rb +6 -0
  10. data/lib/squeel/adapters/active_record/join_association.rb +90 -0
  11. data/lib/squeel/adapters/active_record/join_dependency.rb +68 -0
  12. data/lib/squeel/adapters/active_record/relation.rb +292 -0
  13. data/lib/squeel/configuration.rb +25 -0
  14. data/lib/squeel/constants.rb +23 -0
  15. data/lib/squeel/contexts/join_dependency_context.rb +74 -0
  16. data/lib/squeel/dsl.rb +31 -0
  17. data/lib/squeel/nodes.rb +10 -0
  18. data/lib/squeel/nodes/and.rb +8 -0
  19. data/lib/squeel/nodes/binary.rb +23 -0
  20. data/lib/squeel/nodes/function.rb +84 -0
  21. data/lib/squeel/nodes/join.rb +51 -0
  22. data/lib/squeel/nodes/key_path.rb +127 -0
  23. data/lib/squeel/nodes/nary.rb +35 -0
  24. data/lib/squeel/nodes/not.rb +8 -0
  25. data/lib/squeel/nodes/operation.rb +23 -0
  26. data/lib/squeel/nodes/operators.rb +27 -0
  27. data/lib/squeel/nodes/or.rb +8 -0
  28. data/lib/squeel/nodes/order.rb +35 -0
  29. data/lib/squeel/nodes/predicate.rb +49 -0
  30. data/lib/squeel/nodes/predicate_operators.rb +17 -0
  31. data/lib/squeel/nodes/stub.rb +113 -0
  32. data/lib/squeel/nodes/unary.rb +22 -0
  33. data/lib/squeel/predicate_methods.rb +22 -0
  34. data/lib/squeel/predicate_methods/function.rb +9 -0
  35. data/lib/squeel/predicate_methods/predicate.rb +11 -0
  36. data/lib/squeel/predicate_methods/stub.rb +9 -0
  37. data/lib/squeel/predicate_methods/symbol.rb +9 -0
  38. data/lib/squeel/version.rb +3 -0
  39. data/lib/squeel/visitors.rb +3 -0
  40. data/lib/squeel/visitors/base.rb +46 -0
  41. data/lib/squeel/visitors/order_visitor.rb +107 -0
  42. data/lib/squeel/visitors/predicate_visitor.rb +179 -0
  43. data/lib/squeel/visitors/select_visitor.rb +103 -0
  44. data/spec/blueprints/articles.rb +5 -0
  45. data/spec/blueprints/comments.rb +5 -0
  46. data/spec/blueprints/notes.rb +3 -0
  47. data/spec/blueprints/people.rb +4 -0
  48. data/spec/blueprints/tags.rb +3 -0
  49. data/spec/console.rb +22 -0
  50. data/spec/core_ext/symbol_spec.rb +68 -0
  51. data/spec/helpers/squeel_helper.rb +5 -0
  52. data/spec/spec_helper.rb +30 -0
  53. data/spec/squeel/adapters/active_record/join_association_spec.rb +18 -0
  54. data/spec/squeel/adapters/active_record/join_depdendency_spec.rb +60 -0
  55. data/spec/squeel/adapters/active_record/relation_spec.rb +437 -0
  56. data/spec/squeel/contexts/join_dependency_context_spec.rb +43 -0
  57. data/spec/squeel/dsl_spec.rb +73 -0
  58. data/spec/squeel/nodes/function_spec.rb +149 -0
  59. data/spec/squeel/nodes/join_spec.rb +27 -0
  60. data/spec/squeel/nodes/key_path_spec.rb +92 -0
  61. data/spec/squeel/nodes/operation_spec.rb +149 -0
  62. data/spec/squeel/nodes/operators_spec.rb +87 -0
  63. data/spec/squeel/nodes/order_spec.rb +30 -0
  64. data/spec/squeel/nodes/predicate_operators_spec.rb +88 -0
  65. data/spec/squeel/nodes/predicate_spec.rb +92 -0
  66. data/spec/squeel/nodes/stub_spec.rb +178 -0
  67. data/spec/squeel/visitors/order_visitor_spec.rb +128 -0
  68. data/spec/squeel/visitors/predicate_visitor_spec.rb +267 -0
  69. data/spec/squeel/visitors/select_visitor_spec.rb +115 -0
  70. data/spec/support/schema.rb +101 -0
  71. data/squeel.gemspec +44 -0
  72. metadata +221 -0
@@ -0,0 +1,87 @@
1
+ require 'spec_helper'
2
+
3
+ module Squeel
4
+ module Nodes
5
+ describe Operators do
6
+
7
+ [:+, :-, :*, :/].each do |operator|
8
+ describe "#{operator}" do
9
+ it "creates Operations with #{operator} operator from stubs" do
10
+ left = Stub.new(:stubby_mcstubbenstein)
11
+ node = left.send(operator, 1)
12
+ node.should be_an Operation
13
+ node.left.should eq left
14
+ node.operator.should eq operator
15
+ node.right.should eq 1
16
+ end
17
+
18
+ it "creates Operations with #{operator} operator from key paths" do
19
+ left = KeyPath.new(:first, :second)
20
+ node = left.send(operator, 1)
21
+ node.should be_an Operation
22
+ node.left.should eq left
23
+ node.operator.should eq operator
24
+ node.right.should eq 1
25
+ end
26
+
27
+ it "creates Operations with #{operator} operator from functions" do
28
+ left = Function.new(:name, ["arg1", "arg2"])
29
+ node = left.send(operator, 1)
30
+ node.should be_an Operation
31
+ node.left.should eq left
32
+ node.operator.should eq operator
33
+ node.right.should eq 1
34
+ end
35
+
36
+ it "creates Operations with #{operator} operator from operations" do
37
+ left = Stub.new(:stubby_mcstubbenstein) + 1
38
+ node = left.send(operator, 1)
39
+ node.should be_an Operation
40
+ node.left.should eq left
41
+ node.operator.should eq operator
42
+ node.right.should eq 1
43
+ end
44
+ end
45
+ end
46
+
47
+ describe '#op' do
48
+ it "creates Operations with custom operator from stubs" do
49
+ left = Stub.new(:stubby_mcstubbenstein)
50
+ node = left.op('||', 1)
51
+ node.should be_an Operation
52
+ node.left.should eq left
53
+ node.operator.should eq '||'
54
+ node.right.should eq 1
55
+ end
56
+
57
+ it "creates Operations with custom operator from key paths" do
58
+ left = KeyPath.new(:first, :second)
59
+ node = left.op('||', 1)
60
+ node.should be_an Operation
61
+ node.left.should eq left
62
+ node.operator.should eq '||'
63
+ node.right.should eq 1
64
+ end
65
+
66
+ it "creates Operations with custom operator from functions" do
67
+ left = Function.new(:name, ["arg1", "arg2"])
68
+ node = left.op('||', 1)
69
+ node.should be_an Operation
70
+ node.left.should eq left
71
+ node.operator.should eq '||'
72
+ node.right.should eq 1
73
+ end
74
+
75
+ it "creates Operations with custom operator from operations" do
76
+ left = Stub.new(:stubby_mcstubbenstein) + 1
77
+ node = left.op('||', 1)
78
+ node.should be_an Operation
79
+ node.left.should eq left
80
+ node.operator.should eq '||'
81
+ node.right.should eq 1
82
+ end
83
+ end
84
+
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ module Squeel
4
+ module Nodes
5
+ describe Order do
6
+
7
+ it 'requires a direction of -1 or 1' do
8
+ expect { Order.new :attribute, 0 }.to raise_error ArgumentError
9
+ end
10
+
11
+ it 'defaults to ascending order' do
12
+ @o = Order.new :attribute
13
+ @o.should be_ascending
14
+ end
15
+
16
+ it 'allows reversal of order' do
17
+ @o = Order.new :attribute, 1
18
+ @o.reverse!
19
+ @o.should be_descending
20
+ end
21
+
22
+ it 'allows setting order' do
23
+ @o = Order.new :attribute
24
+ @o.desc
25
+ @o.should be_descending
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+
3
+ module Squeel
4
+ module Nodes
5
+ describe PredicateOperators do
6
+
7
+ describe '&' do
8
+ it 'creates And nodes from hashes' do
9
+ left = {:name.matches => 'J%'}
10
+ right = {:name.matches => '%e'}
11
+ n = left & right
12
+ n.should be_a And
13
+ n.children.should eq [left, right]
14
+ end
15
+
16
+ it 'creates And nodes from predicates' do
17
+ left = :name.matches % 'J%'
18
+ right = :name.matches % '%e'
19
+ n = left & right
20
+ n.should be_a And
21
+ n.children.should eq [left, right]
22
+ end
23
+
24
+ it 'appends nodes to children from other And nodes' do
25
+ left = :name.matches % 'J%' & :name.matches % '%e'
26
+ right = :id.gt % 0
27
+ expected = left.children + [right]
28
+ left & right
29
+ left.should be_a And
30
+ left.children.should eq expected
31
+ end
32
+ end
33
+
34
+ describe '|' do
35
+ it 'creates Or nodes from hashes' do
36
+ left = {:name.matches => 'J%'}
37
+ right = {:name.matches => '%e'}
38
+ n = left | right
39
+ n.should be_a Or
40
+ n.left.should eq left
41
+ n.right.should eq right
42
+ end
43
+
44
+ it 'creates Or nodes from predicates' do
45
+ left = :name.matches % 'J%'
46
+ right = :name.matches % '%e'
47
+ n = left | right
48
+ n.should be_a Or
49
+ n.left.should eq left
50
+ n.right.should eq right
51
+ end
52
+
53
+ it 'creates Or nodes from other Or nodes' do
54
+ left = :name.matches % 'J%' | :name.matches % '%e'
55
+ right = :id.gt % 0 | :id.lt % 100
56
+ n = left | right
57
+ n.should be_a Or
58
+ n.left.should eq left
59
+ n.right.should eq right
60
+ end
61
+ end
62
+
63
+ describe '-@' do
64
+ it 'creates Not nodes from hashes' do
65
+ expr = {:name => 'Joe'}
66
+ n = - expr
67
+ n.should be_a Not
68
+ n.expr.should eq expr
69
+ end
70
+
71
+ it 'creates Not nodes from predicates' do
72
+ expr = :name.matches % 'J%'
73
+ n = - expr
74
+ n.should be_a Not
75
+ n.expr.should eq expr
76
+ end
77
+
78
+ it 'creates Not nodes from other Not nodes' do
79
+ expr = -(:name.matches % '%e')
80
+ n = - expr
81
+ n.should be_a Not
82
+ n.expr.should eq expr
83
+ end
84
+ end
85
+
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,92 @@
1
+ require 'spec_helper'
2
+
3
+ module Squeel
4
+ module Nodes
5
+ describe Predicate do
6
+
7
+ context 'ARel predicate methods' do
8
+ before do
9
+ @p = Predicate.new(:attribute)
10
+ end
11
+
12
+ Squeel::Constants::PREDICATES.each do |method_name|
13
+ it "creates #{method_name} predicates with no value" do
14
+ predicate = @p.send(method_name)
15
+ predicate.expr.should eq :attribute
16
+ predicate.method_name.should eq method_name
17
+ predicate.value?.should be_false
18
+ end
19
+
20
+ it "creates #{method_name} predicates with a value" do
21
+ predicate = @p.send(method_name, 'value')
22
+ predicate.expr.should eq :attribute
23
+ predicate.method_name.should eq method_name
24
+ predicate.value.should eq 'value'
25
+ end
26
+ end
27
+
28
+ Squeel::Constants::PREDICATE_ALIASES.each do |method_name, aliases|
29
+ aliases.each do |aliaz|
30
+ ['', '_any', '_all'].each do |suffix|
31
+ it "creates #{method_name.to_s + suffix} predicates with no value using the alias #{aliaz.to_s + suffix}" do
32
+ predicate = @p.send(aliaz.to_s + suffix)
33
+ predicate.expr.should eq :attribute
34
+ predicate.method_name.should eq "#{method_name}#{suffix}".to_sym
35
+ predicate.value?.should be_false
36
+ end
37
+
38
+ it "creates #{method_name.to_s + suffix} predicates with a value using the alias #{aliaz.to_s + suffix}" do
39
+ predicate = @p.send((aliaz.to_s + suffix), 'value')
40
+ predicate.expr.should eq :attribute
41
+ predicate.method_name.should eq "#{method_name}#{suffix}".to_sym
42
+ predicate.value.should eq 'value'
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ it 'accepts a value on instantiation' do
50
+ @p = Predicate.new :name, :eq, 'value'
51
+ @p.value.should eq 'value'
52
+ end
53
+
54
+ it 'sets value via accessor' do
55
+ @p = Predicate.new :name, :eq
56
+ @p.value = 'value'
57
+ @p.value.should eq 'value'
58
+ end
59
+
60
+ it 'sets value via %' do
61
+ @p = Predicate.new :name, :eq
62
+ @p % 'value'
63
+ @p.value.should eq 'value'
64
+ end
65
+
66
+ it 'can be inquired for value presence' do
67
+ @p = Predicate.new :name, :eq
68
+ @p.value?.should be_false
69
+ @p.value = 'value'
70
+ @p.value?.should be_true
71
+ end
72
+
73
+ it 'can be ORed with another predicate' do
74
+ left = Predicate.new :name, :eq, 'Joe'
75
+ right = Predicate.new :name, :eq, 'Bob'
76
+ combined = left | right
77
+ combined.should be_a Nodes::Or
78
+ combined.left.should eq left
79
+ combined.right.should eq right
80
+ end
81
+
82
+ it 'can be ANDed with another predicate' do
83
+ left = Predicate.new :name, :eq, 'Joe'
84
+ right = Predicate.new :name, :eq, 'Bob'
85
+ combined = left & right
86
+ combined.should be_a Nodes::And
87
+ combined.children.should eq [left, right]
88
+ end
89
+
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,178 @@
1
+ require 'spec_helper'
2
+
3
+ module Squeel
4
+ module Nodes
5
+ describe Stub do
6
+ before do
7
+ @s = Stub.new :attribute
8
+ end
9
+
10
+ it 'hashes like a symbol' do
11
+ @s.hash.should eq :attribute.hash
12
+ end
13
+
14
+ it 'returns its symbol when sent to_sym' do
15
+ @s.to_sym.should eq :attribute
16
+ end
17
+
18
+ it 'returns a string matching its symbol when sent to_s' do
19
+ @s.to_s.should eq 'attribute'
20
+ end
21
+
22
+ it 'merges against matching stubs' do
23
+ hash1 = {Stub.new(:attribute) => 1}
24
+ hash2 = {Stub.new(:attribute) => 2}
25
+ merged = hash1.merge(hash2)
26
+ merged.keys.should have(1).key
27
+ merged[Stub.new(:attribute)].should eq 2
28
+ end
29
+
30
+ Squeel::Constants::PREDICATES.each do |method_name|
31
+ it "creates #{method_name} predicates with no value" do
32
+ predicate = @s.send(method_name)
33
+ predicate.expr.should eq :attribute
34
+ predicate.method_name.should eq method_name
35
+ predicate.value?.should be_false
36
+ end
37
+
38
+ it "creates #{method_name} predicates with a value" do
39
+ predicate = @s.send(method_name, 'value')
40
+ predicate.expr.should eq :attribute
41
+ predicate.method_name.should eq method_name
42
+ predicate.value.should eq 'value'
43
+ end
44
+ end
45
+
46
+ Squeel::Constants::PREDICATE_ALIASES.each do |method_name, aliases|
47
+ aliases.each do |aliaz|
48
+ ['', '_any', '_all'].each do |suffix|
49
+ it "creates #{method_name.to_s + suffix} predicates with no value using the alias #{aliaz.to_s + suffix}" do
50
+ predicate = @s.send(aliaz.to_s + suffix)
51
+ predicate.expr.should eq :attribute
52
+ predicate.method_name.should eq "#{method_name}#{suffix}".to_sym
53
+ predicate.value?.should be_false
54
+ end
55
+
56
+ it "creates #{method_name.to_s + suffix} predicates with a value using the alias #{aliaz.to_s + suffix}" do
57
+ predicate = @s.send((aliaz.to_s + suffix), 'value')
58
+ predicate.expr.should eq :attribute
59
+ predicate.method_name.should eq "#{method_name}#{suffix}".to_sym
60
+ predicate.value.should eq 'value'
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ it 'creates eq predicates with ==' do
67
+ predicate = @s == 1
68
+ predicate.expr.should eq :attribute
69
+ predicate.method_name.should eq :eq
70
+ predicate.value.should eq 1
71
+ end
72
+
73
+ it 'creates not_eq predicates with ^' do
74
+ predicate = @s ^ 1
75
+ predicate.expr.should eq :attribute
76
+ predicate.method_name.should eq :not_eq
77
+ predicate.value.should eq 1
78
+ end
79
+
80
+ it 'creates not_eq predicates with !=' do
81
+ predicate = @s != 1
82
+ predicate.expr.should eq :attribute
83
+ predicate.method_name.should eq :not_eq
84
+ predicate.value.should eq 1
85
+ end if respond_to?('!=')
86
+
87
+ it 'creates in predicates with >>' do
88
+ predicate = @s >> [1,2,3]
89
+ predicate.expr.should eq :attribute
90
+ predicate.method_name.should eq :in
91
+ predicate.value.should eq [1,2,3]
92
+ end
93
+
94
+ it 'creates not_in predicates with <<' do
95
+ predicate = @s << [1,2,3]
96
+ predicate.expr.should eq :attribute
97
+ predicate.method_name.should eq :not_in
98
+ predicate.value.should eq [1,2,3]
99
+ end
100
+
101
+ it 'creates matches predicates with =~' do
102
+ predicate = @s =~ '%bob%'
103
+ predicate.expr.should eq :attribute
104
+ predicate.method_name.should eq :matches
105
+ predicate.value.should eq '%bob%'
106
+ end
107
+
108
+ it 'creates does_not_match predicates with !~' do
109
+ predicate = @s !~ '%bob%'
110
+ predicate.expr.should eq :attribute
111
+ predicate.method_name.should eq :does_not_match
112
+ predicate.value.should eq '%bob%'
113
+ end if respond_to?('!~')
114
+
115
+ it 'creates gt predicates with >' do
116
+ predicate = @s > 1
117
+ predicate.expr.should eq :attribute
118
+ predicate.method_name.should eq :gt
119
+ predicate.value.should eq 1
120
+ end
121
+
122
+ it 'creates gteq predicates with >=' do
123
+ predicate = @s >= 1
124
+ predicate.expr.should eq :attribute
125
+ predicate.method_name.should eq :gteq
126
+ predicate.value.should eq 1
127
+ end
128
+
129
+ it 'creates lt predicates with <' do
130
+ predicate = @s < 1
131
+ predicate.expr.should eq :attribute
132
+ predicate.method_name.should eq :lt
133
+ predicate.value.should eq 1
134
+ end
135
+
136
+ it 'creates lteq predicates with <=' do
137
+ predicate = @s <= 1
138
+ predicate.expr.should eq :attribute
139
+ predicate.method_name.should eq :lteq
140
+ predicate.value.should eq 1
141
+ end
142
+
143
+ it 'creates ascending orders' do
144
+ order = @s.asc
145
+ order.should be_ascending
146
+ end
147
+
148
+ it 'creates descending orders' do
149
+ order = @s.desc
150
+ order.should be_descending
151
+ end
152
+
153
+ it 'creates inner joins' do
154
+ join = @s.inner
155
+ join.should be_a Join
156
+ join.type.should eq Arel::InnerJoin
157
+ end
158
+
159
+ it 'creates outer joins' do
160
+ join = @s.outer
161
+ join.should be_a Join
162
+ join.type.should eq Arel::OuterJoin
163
+ end
164
+
165
+ it 'creates functions with #func' do
166
+ function = @s.func
167
+ function.should be_a Function
168
+ end
169
+
170
+ it 'creates functions with #[]' do
171
+ function = @s[1, 2, 3]
172
+ function.should be_a Function
173
+ function.args.should eq [1, 2, 3]
174
+ end
175
+
176
+ end
177
+ end
178
+ end