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