squeel 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +8 -0
- data/LICENSE +20 -0
- data/README.rdoc +41 -0
- data/Rakefile +19 -0
- data/lib/core_ext/hash.rb +13 -0
- data/lib/core_ext/symbol.rb +36 -0
- data/lib/squeel.rb +26 -0
- data/lib/squeel/adapters/active_record.rb +6 -0
- data/lib/squeel/adapters/active_record/join_association.rb +90 -0
- data/lib/squeel/adapters/active_record/join_dependency.rb +68 -0
- data/lib/squeel/adapters/active_record/relation.rb +292 -0
- data/lib/squeel/configuration.rb +25 -0
- data/lib/squeel/constants.rb +23 -0
- data/lib/squeel/contexts/join_dependency_context.rb +74 -0
- data/lib/squeel/dsl.rb +31 -0
- data/lib/squeel/nodes.rb +10 -0
- data/lib/squeel/nodes/and.rb +8 -0
- data/lib/squeel/nodes/binary.rb +23 -0
- data/lib/squeel/nodes/function.rb +84 -0
- data/lib/squeel/nodes/join.rb +51 -0
- data/lib/squeel/nodes/key_path.rb +127 -0
- data/lib/squeel/nodes/nary.rb +35 -0
- data/lib/squeel/nodes/not.rb +8 -0
- data/lib/squeel/nodes/operation.rb +23 -0
- data/lib/squeel/nodes/operators.rb +27 -0
- data/lib/squeel/nodes/or.rb +8 -0
- data/lib/squeel/nodes/order.rb +35 -0
- data/lib/squeel/nodes/predicate.rb +49 -0
- data/lib/squeel/nodes/predicate_operators.rb +17 -0
- data/lib/squeel/nodes/stub.rb +113 -0
- data/lib/squeel/nodes/unary.rb +22 -0
- data/lib/squeel/predicate_methods.rb +22 -0
- data/lib/squeel/predicate_methods/function.rb +9 -0
- data/lib/squeel/predicate_methods/predicate.rb +11 -0
- data/lib/squeel/predicate_methods/stub.rb +9 -0
- data/lib/squeel/predicate_methods/symbol.rb +9 -0
- data/lib/squeel/version.rb +3 -0
- data/lib/squeel/visitors.rb +3 -0
- data/lib/squeel/visitors/base.rb +46 -0
- data/lib/squeel/visitors/order_visitor.rb +107 -0
- data/lib/squeel/visitors/predicate_visitor.rb +179 -0
- data/lib/squeel/visitors/select_visitor.rb +103 -0
- data/spec/blueprints/articles.rb +5 -0
- data/spec/blueprints/comments.rb +5 -0
- data/spec/blueprints/notes.rb +3 -0
- data/spec/blueprints/people.rb +4 -0
- data/spec/blueprints/tags.rb +3 -0
- data/spec/console.rb +22 -0
- data/spec/core_ext/symbol_spec.rb +68 -0
- data/spec/helpers/squeel_helper.rb +5 -0
- data/spec/spec_helper.rb +30 -0
- data/spec/squeel/adapters/active_record/join_association_spec.rb +18 -0
- data/spec/squeel/adapters/active_record/join_depdendency_spec.rb +60 -0
- data/spec/squeel/adapters/active_record/relation_spec.rb +437 -0
- data/spec/squeel/contexts/join_dependency_context_spec.rb +43 -0
- data/spec/squeel/dsl_spec.rb +73 -0
- data/spec/squeel/nodes/function_spec.rb +149 -0
- data/spec/squeel/nodes/join_spec.rb +27 -0
- data/spec/squeel/nodes/key_path_spec.rb +92 -0
- data/spec/squeel/nodes/operation_spec.rb +149 -0
- data/spec/squeel/nodes/operators_spec.rb +87 -0
- data/spec/squeel/nodes/order_spec.rb +30 -0
- data/spec/squeel/nodes/predicate_operators_spec.rb +88 -0
- data/spec/squeel/nodes/predicate_spec.rb +92 -0
- data/spec/squeel/nodes/stub_spec.rb +178 -0
- data/spec/squeel/visitors/order_visitor_spec.rb +128 -0
- data/spec/squeel/visitors/predicate_visitor_spec.rb +267 -0
- data/spec/squeel/visitors/select_visitor_spec.rb +115 -0
- data/spec/support/schema.rb +101 -0
- data/squeel.gemspec +44 -0
- metadata +221 -0
@@ -0,0 +1,128 @@
|
|
1
|
+
module Squeel
|
2
|
+
module Visitors
|
3
|
+
describe OrderVisitor do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@jd = ActiveRecord::Associations::JoinDependency.
|
7
|
+
new(Person, {
|
8
|
+
:children => {
|
9
|
+
:children => {
|
10
|
+
:parent => :parent
|
11
|
+
}
|
12
|
+
}
|
13
|
+
}, [])
|
14
|
+
@c = Squeel::Contexts::JoinDependencyContext.new(@jd)
|
15
|
+
@v = OrderVisitor.new(@c)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'creates a bare ARel attribute given a symbol with no asc/desc' do
|
19
|
+
attribute = @v.accept(:name)
|
20
|
+
attribute.should be_a Arel::Attribute
|
21
|
+
attribute.name.should eq :name
|
22
|
+
attribute.relation.name.should eq 'people'
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'creates the ordering against the proper table for nested hashes' do
|
26
|
+
orders = @v.accept({
|
27
|
+
:children => {
|
28
|
+
:children => {
|
29
|
+
:parent => {
|
30
|
+
:parent => :name.asc
|
31
|
+
}
|
32
|
+
}
|
33
|
+
}
|
34
|
+
})
|
35
|
+
orders.should be_a Array
|
36
|
+
ordering = orders.first
|
37
|
+
ordering.should be_a Arel::Nodes::Ordering
|
38
|
+
ordering.expr.relation.table_alias.should eq 'parents_people_2'
|
39
|
+
ordering.direction.should eq :asc
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'does not alter values it is unable to accept' do
|
43
|
+
orders = @v.accept(['THIS PARAMETER', 'WHAT DOES IT MEAN???'])
|
44
|
+
orders.should eq ['THIS PARAMETER', 'WHAT DOES IT MEAN???']
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'treats keypath keys like nested hashes' do
|
48
|
+
ordering = @v.accept(Nodes::Stub.new(:children).children.parent.parent.name.asc)
|
49
|
+
ordering.should be_a Arel::Nodes::Ordering
|
50
|
+
ordering.expr.relation.table_alias.should eq 'parents_people_2'
|
51
|
+
ordering.direction.should eq :asc
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'honors absolute keypaths' do
|
55
|
+
orders = @v.accept(dsl{{children => {children => ~children.children.name.asc}}})
|
56
|
+
orders.should be_a Array
|
57
|
+
ordering = orders.first
|
58
|
+
ordering.expr.relation.table_alias.should eq 'children_people_2'
|
59
|
+
ordering.direction.should eq :asc
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'allows hashes with keypath keys' do
|
63
|
+
orders = @v.accept(Nodes::Stub.new(:children).children.parent.parent => :name.asc)
|
64
|
+
orders.should be_a Array
|
65
|
+
ordering = orders.first
|
66
|
+
ordering.should be_a Arel::Nodes::Ordering
|
67
|
+
ordering.expr.relation.table_alias.should eq 'parents_people_2'
|
68
|
+
ordering.direction.should eq :asc
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'creates an ARel NamedFunction node for a Function node' do
|
72
|
+
function = @v.accept(:find_in_set.func())
|
73
|
+
function.should be_a Arel::Nodes::NamedFunction
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'maps symbols in Function args to ARel attributes' do
|
77
|
+
function = @v.accept(:find_in_set.func(:id, '1,2,3'))
|
78
|
+
function.to_sql.should match /find_in_set\("people"."id", '1,2,3'\)/
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'accepts Order with Function expression' do
|
82
|
+
function = @v.accept(dsl{find_in_set(children.children.id, '1,2,3').desc})
|
83
|
+
function.to_sql.should match /find_in_set\("children_people_2"."id", '1,2,3'\) DESC/
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'accepts keypaths as function args' do
|
87
|
+
function = @v.accept(dsl{find_in_set(children.children.id, '1,2,3')})
|
88
|
+
function.to_sql.should match /find_in_set\("children_people_2"."id", '1,2,3'\)/
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'sets the alias on the ARel NamedFunction from the Function alias' do
|
92
|
+
function = @v.accept(:find_in_set.func(:id, '1,2,3').as('newname'))
|
93
|
+
function.to_sql.should match /newname/
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'creates an ARel Addition node for an Operation node with + as operator' do
|
97
|
+
operation = @v.accept(dsl{id + 1})
|
98
|
+
operation.should be_a Arel::Nodes::Addition
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'creates an ARel Subtraction node for an Operation node with - as operator' do
|
102
|
+
operation = @v.accept(dsl{id - 1})
|
103
|
+
operation.should be_a Arel::Nodes::Subtraction
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'creates an ARel Multiplication node for an Operation node with * as operator' do
|
107
|
+
operation = @v.accept(dsl{id * 1})
|
108
|
+
operation.should be_a Arel::Nodes::Multiplication
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'creates an ARel Division node for an Operation node with / as operator' do
|
112
|
+
operation = @v.accept(dsl{id / 1})
|
113
|
+
operation.should be_a Arel::Nodes::Division
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'sets the alias on an InfixOperation from the Operation alias' do
|
117
|
+
operation = @v.accept(dsl{(id + 1).as(:incremented_id)})
|
118
|
+
operation.to_sql.should match /incremented_id/
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'accepts Order with Operation expression' do
|
122
|
+
operation = @v.accept(dsl{(id / 1).desc})
|
123
|
+
operation.to_sql.should match /"people"."id" \/ 1 DESC/
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,267 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Squeel
|
4
|
+
module Visitors
|
5
|
+
describe PredicateVisitor do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@jd = ActiveRecord::Associations::JoinDependency.
|
9
|
+
new(Person, {
|
10
|
+
:children => {
|
11
|
+
:children => {
|
12
|
+
:parent => :parent
|
13
|
+
}
|
14
|
+
}
|
15
|
+
}, [])
|
16
|
+
@c = Squeel::Contexts::JoinDependencyContext.new(@jd)
|
17
|
+
@v = PredicateVisitor.new(@c)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'creates Equality nodes for simple hashes' do
|
21
|
+
predicate = @v.accept(:name => 'Joe')
|
22
|
+
predicate.should be_a Arel::Nodes::Equality
|
23
|
+
predicate.left.name.should eq :name
|
24
|
+
predicate.right.should eq 'Joe'
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'creates In nodes for simple hashes with an array as a value' do
|
28
|
+
predicate = @v.accept(:name => ['Joe', 'Bob'])
|
29
|
+
predicate.should be_a Arel::Nodes::In
|
30
|
+
predicate.left.name.should eq :name
|
31
|
+
predicate.right.should eq ['Joe', 'Bob']
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'creates the node against the proper table for nested hashes' do
|
35
|
+
predicate = @v.accept({
|
36
|
+
:children => {
|
37
|
+
:children => {
|
38
|
+
:parent => {
|
39
|
+
:parent => {
|
40
|
+
:name => 'Joe'
|
41
|
+
}
|
42
|
+
}
|
43
|
+
}
|
44
|
+
}
|
45
|
+
})
|
46
|
+
predicate.should be_a Arel::Nodes::Equality
|
47
|
+
predicate.left.relation.table_alias.should eq 'parents_people_2'
|
48
|
+
predicate.right.should eq 'Joe'
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'treats keypath keys like nested hashes' do
|
52
|
+
standard = @v.accept({
|
53
|
+
:children => {
|
54
|
+
:children => {
|
55
|
+
:parent => {
|
56
|
+
:parent => {
|
57
|
+
:name => 'Joe'
|
58
|
+
}
|
59
|
+
}
|
60
|
+
}
|
61
|
+
}
|
62
|
+
})
|
63
|
+
keypath = @v.accept(Nodes::Stub.new(:children).children.parent.parent.name => 'Joe')
|
64
|
+
keypath.to_sql.should eq standard.to_sql
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'honors absolute keypaths' do
|
68
|
+
standard = @v.accept({
|
69
|
+
:children => {
|
70
|
+
:children => {
|
71
|
+
:name => 'Joe'
|
72
|
+
}
|
73
|
+
}
|
74
|
+
})
|
75
|
+
keypath = @v.accept(dsl{{children => {children => {~children.children.name => 'Joe'}}}})
|
76
|
+
keypath.to_sql.should eq standard.to_sql
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'allows incomplete predicates (missing value) as keys' do
|
80
|
+
standard = @v.accept({
|
81
|
+
:children => {
|
82
|
+
:children => {
|
83
|
+
:parent => {
|
84
|
+
:parent => {
|
85
|
+
:name.matches => 'Joe%'
|
86
|
+
}
|
87
|
+
}
|
88
|
+
}
|
89
|
+
}
|
90
|
+
})
|
91
|
+
keypath = @v.accept(Nodes::Stub.new(:children).children.parent.parent.name.matches => 'Joe%')
|
92
|
+
keypath.to_sql.should eq standard.to_sql
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'allows hashes as values with keypath keys' do
|
96
|
+
standard = @v.accept({
|
97
|
+
:children => {
|
98
|
+
:children => {
|
99
|
+
:parent => {
|
100
|
+
:parent => {
|
101
|
+
:name => 'Joe'
|
102
|
+
}
|
103
|
+
}
|
104
|
+
}
|
105
|
+
}
|
106
|
+
})
|
107
|
+
keypath = @v.accept(Nodes::Stub.new(:children).children.parent.parent => {:name => 'Joe'})
|
108
|
+
keypath.to_sql.should eq standard.to_sql
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'contextualizes Stub values' do
|
112
|
+
predicate = @v.accept(dsl{{name => name}})
|
113
|
+
predicate.should be_a Arel::Nodes::Equality
|
114
|
+
predicate.right.should be_a Arel::Attribute
|
115
|
+
predicate.to_sql.should match /"people"."name" = "people"."name"/
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'contextualizes Symbol values' do
|
119
|
+
predicate = @v.accept(:name => :name)
|
120
|
+
predicate.should be_a Arel::Nodes::Equality
|
121
|
+
predicate.right.should be_a Arel::Attribute
|
122
|
+
predicate.to_sql.should match /"people"."name" = "people"."name"/
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'contextualizes KeyPath values in hashes' do
|
126
|
+
predicate = @v.accept(dsl{{name => children.name}})
|
127
|
+
predicate.should be_a Arel::Nodes::Equality
|
128
|
+
predicate.right.should be_a Arel::Attribute
|
129
|
+
predicate.to_sql.should match /"people"."name" = "children_people"."name"/
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'contextualizes KeyPath values in predicates' do
|
133
|
+
predicate = @v.accept(dsl{name == children.name})
|
134
|
+
predicate.should be_a Arel::Nodes::Equality
|
135
|
+
predicate.right.should be_a Arel::Attribute
|
136
|
+
predicate.to_sql.should match /"people"."name" = "children_people"."name"/
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'creates a node of the proper type when a hash has a Predicate as a key' do
|
140
|
+
predicate = @v.accept(:name.matches => 'Joe%')
|
141
|
+
predicate.should be_a Arel::Nodes::Matches
|
142
|
+
predicate.left.name.should eq :name
|
143
|
+
predicate.right.should eq 'Joe%'
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'treats hash keys as an association when there is an array of "acceptables" on the value side' do
|
147
|
+
predicate = @v.accept(:children => [:name.matches % 'Joe%', :name.eq % 'Bob'])
|
148
|
+
predicate.should be_a Arel::Nodes::Grouping
|
149
|
+
predicate.expr.should be_a Arel::Nodes::And
|
150
|
+
predicate.expr.children.should have(2).items
|
151
|
+
predicate.expr.children.first.should be_a Arel::Nodes::Matches
|
152
|
+
predicate.expr.children.first.left.relation.table_alias.should eq 'children_people'
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'treats hash keys as an association when there is an Or on the value side' do
|
156
|
+
predicate = @v.accept(:children => (:name.matches % 'Joe%' | :name.matches % 'Bob%'))
|
157
|
+
predicate.should be_a Arel::Nodes::Grouping
|
158
|
+
predicate.expr.should be_a Arel::Nodes::Or
|
159
|
+
predicate.expr.left.should be_a Arel::Nodes::Matches
|
160
|
+
predicate.expr.left.left.relation.table_alias.should eq 'children_people'
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'treats hash keys as an association when there is an And on the value side' do
|
164
|
+
predicate = @v.accept(:children => (:name.matches % 'Joe%' & :name.matches % 'Bob%'))
|
165
|
+
predicate.should be_a Arel::Nodes::Grouping
|
166
|
+
predicate.expr.should be_a Arel::Nodes::And
|
167
|
+
predicate.expr.children.should have(2).items
|
168
|
+
predicate.expr.children.first.should be_a Arel::Nodes::Matches
|
169
|
+
predicate.expr.children.first.left.relation.table_alias.should eq 'children_people'
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'treats hash keys as an association when there is a Not on the value side' do
|
173
|
+
predicate = @v.accept(:children => -(:name.matches % 'Joe%'))
|
174
|
+
predicate.should be_a Arel::Nodes::Not
|
175
|
+
predicate.expr.should be_a Arel::Nodes::Matches
|
176
|
+
predicate.expr.left.relation.table_alias.should eq 'children_people'
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'treats hash keys as an association when there is a Predicate on the value side' do
|
180
|
+
predicate = @v.accept(:children => (:name.matches % 'Joe%'))
|
181
|
+
predicate.should be_a Arel::Nodes::Matches
|
182
|
+
predicate.left.relation.table_alias.should eq 'children_people'
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'treats hash keys as an association when there is a KeyPath on the value side' do
|
186
|
+
predicate = @v.accept(:children => Nodes::Stub.new(:children).name.eq('Joe'))
|
187
|
+
predicate.should be_a Arel::Nodes::Equality
|
188
|
+
predicate.left.relation.table_alias.should eq 'children_people_2'
|
189
|
+
predicate.left.name.should eq :name
|
190
|
+
predicate.right.should eq 'Joe'
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'creates an ARel Grouping node containing an Or node for Or nodes' do
|
194
|
+
left = :name.matches % 'Joe%'
|
195
|
+
right = :id.gt % 1
|
196
|
+
predicate = @v.accept(left | right)
|
197
|
+
predicate.should be_a Arel::Nodes::Grouping
|
198
|
+
predicate.expr.should be_a Arel::Nodes::Or
|
199
|
+
predicate.expr.left.should be_a Arel::Nodes::Matches
|
200
|
+
predicate.expr.right.should be_a Arel::Nodes::GreaterThan
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'creates an ARel Not node for a Not node' do
|
204
|
+
expr = -(:name.matches % 'Joe%')
|
205
|
+
predicate = @v.accept(expr)
|
206
|
+
predicate.should be_a Arel::Nodes::Not
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'creates an ARel NamedFunction node for a Function node' do
|
210
|
+
function = @v.accept(:find_in_set.func())
|
211
|
+
function.should be_a Arel::Nodes::NamedFunction
|
212
|
+
end
|
213
|
+
|
214
|
+
it 'maps symbols in Function args to ARel attributes' do
|
215
|
+
function = @v.accept(:find_in_set.func(:id, '1,2,3'))
|
216
|
+
function.to_sql.should match /"people"."id"/
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'sets the alias on the ARel NamedFunction from the Function alias' do
|
220
|
+
function = @v.accept(:find_in_set.func(:id, '1,2,3').as('newname'))
|
221
|
+
function.to_sql.should match /newname/
|
222
|
+
end
|
223
|
+
|
224
|
+
it 'creates an ARel Addition node for an Operation node with + as operator' do
|
225
|
+
operation = @v.accept(dsl{id + 1})
|
226
|
+
operation.should be_a Arel::Nodes::Addition
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'creates an ARel Subtraction node for an Operation node with - as operator' do
|
230
|
+
operation = @v.accept(dsl{id - 1})
|
231
|
+
operation.should be_a Arel::Nodes::Subtraction
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'creates an ARel Multiplication node for an Operation node with * as operator' do
|
235
|
+
operation = @v.accept(dsl{id * 1})
|
236
|
+
operation.should be_a Arel::Nodes::Multiplication
|
237
|
+
end
|
238
|
+
|
239
|
+
it 'creates an ARel Division node for an Operation node with / as operator' do
|
240
|
+
operation = @v.accept(dsl{id / 1})
|
241
|
+
operation.should be_a Arel::Nodes::Division
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'sets the alias on an InfixOperation from the Operation alias' do
|
245
|
+
operation = @v.accept(dsl{(id + 1).as(:incremented_id)})
|
246
|
+
operation.to_sql.should match /incremented_id/
|
247
|
+
end
|
248
|
+
|
249
|
+
context 'with polymorphic joins in the JoinDependency' do
|
250
|
+
before do
|
251
|
+
@jd = ActiveRecord::Associations::JoinDependency.
|
252
|
+
new(Note, dsl{[notable(Article), notable(Person)]}, [])
|
253
|
+
@c = Squeel::Contexts::JoinDependencyContext.new(@jd)
|
254
|
+
@v = PredicateVisitor.new(@c)
|
255
|
+
end
|
256
|
+
|
257
|
+
it 'respects the polymorphic class in conditions' do
|
258
|
+
article_predicate = @v.accept dsl{{notable(Article) => {:title => 'Hello world!'}}}
|
259
|
+
person_predicate = @v.accept dsl{{notable(Person) => {:name => 'Ernie'}}}
|
260
|
+
article_predicate.left.relation.name.should eq 'articles'
|
261
|
+
person_predicate.left.relation.name.should eq 'people'
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module Squeel
|
2
|
+
module Visitors
|
3
|
+
describe SelectVisitor do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@jd = ActiveRecord::Associations::JoinDependency.
|
7
|
+
new(Person, {
|
8
|
+
:children => {
|
9
|
+
:children => {
|
10
|
+
:parent => :parent
|
11
|
+
}
|
12
|
+
}
|
13
|
+
}, [])
|
14
|
+
@c = Squeel::Contexts::JoinDependencyContext.new(@jd)
|
15
|
+
@v = SelectVisitor.new(@c)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'creates a bare ARel attribute given a symbol with no asc/desc' do
|
19
|
+
attribute = @v.accept(:name)
|
20
|
+
attribute.should be_a Arel::Attribute
|
21
|
+
attribute.name.should eq :name
|
22
|
+
attribute.relation.name.should eq 'people'
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'creates the select against the proper table for nested hashes' do
|
26
|
+
selects = @v.accept({
|
27
|
+
:children => {
|
28
|
+
:children => {
|
29
|
+
:parent => {
|
30
|
+
:parent => :name
|
31
|
+
}
|
32
|
+
}
|
33
|
+
}
|
34
|
+
})
|
35
|
+
selects.should be_a Array
|
36
|
+
select = selects.first
|
37
|
+
select.should be_a Arel::Attribute
|
38
|
+
select.relation.table_alias.should eq 'parents_people_2'
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'will not alter values it is unable to accept' do
|
42
|
+
select = @v.accept(['THIS PARAMETER', 'WHAT DOES IT MEAN???'])
|
43
|
+
select.should eq ['THIS PARAMETER', 'WHAT DOES IT MEAN???']
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'treats keypath keys like nested hashes' do
|
47
|
+
select = @v.accept(Nodes::Stub.new(:children).children.parent.parent.name)
|
48
|
+
select.should be_a Arel::Attribute
|
49
|
+
select.relation.table_alias.should eq 'parents_people_2'
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'honors absolute keypaths' do
|
53
|
+
selects = @v.accept(dsl{{children => {children => ~children.children.name}}})
|
54
|
+
selects.should be_a Array
|
55
|
+
select = selects.first
|
56
|
+
select.should be_a Arel::Attribute
|
57
|
+
select.relation.table_alias.should eq 'children_people_2'
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'allows hashes with keypath keys' do
|
61
|
+
selects = @v.accept(Nodes::Stub.new(:children).children.parent.parent => :name)
|
62
|
+
selects.should be_a Array
|
63
|
+
select = selects.first
|
64
|
+
select.should be_a Arel::Attribute
|
65
|
+
select.relation.table_alias.should eq 'parents_people_2'
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'creates an ARel NamedFunction node for a Function node' do
|
69
|
+
function = @v.accept(:find_in_set.func())
|
70
|
+
function.should be_a Arel::Nodes::NamedFunction
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'maps symbols in Function args to ARel attributes' do
|
74
|
+
function = @v.accept(:find_in_set.func(:id, '1,2,3'))
|
75
|
+
function.to_sql.should match /find_in_set\("people"."id", '1,2,3'\)/
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'accepts keypaths as function args' do
|
79
|
+
function = @v.accept(dsl{find_in_set(children.children.id, '1,2,3')})
|
80
|
+
function.to_sql.should match /find_in_set\("children_people_2"."id", '1,2,3'\)/
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'sets the alias on the ARel NamedFunction from the Function alias' do
|
84
|
+
function = @v.accept(:find_in_set.func(:id, '1,2,3').as('newname'))
|
85
|
+
function.to_sql.should match /newname/
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'creates an ARel Addition node for an Operation node with + as operator' do
|
89
|
+
operation = @v.accept(dsl{id + 1})
|
90
|
+
operation.should be_a Arel::Nodes::Addition
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'creates an ARel Subtraction node for an Operation node with - as operator' do
|
94
|
+
operation = @v.accept(dsl{id - 1})
|
95
|
+
operation.should be_a Arel::Nodes::Subtraction
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'creates an ARel Multiplication node for an Operation node with * as operator' do
|
99
|
+
operation = @v.accept(dsl{id * 1})
|
100
|
+
operation.should be_a Arel::Nodes::Multiplication
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'creates an ARel Division node for an Operation node with / as operator' do
|
104
|
+
operation = @v.accept(dsl{id / 1})
|
105
|
+
operation.should be_a Arel::Nodes::Division
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'sets the alias on an InfixOperation from the Operation alias' do
|
109
|
+
operation = @v.accept(dsl{(id + 1).as(:incremented_id)})
|
110
|
+
operation.to_sql.should match /incremented_id/
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|