squeel 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +10 -6
- data/lib/squeel/adapters/active_record/3.0/context.rb +4 -4
- data/lib/squeel/adapters/active_record/3.0/relation_extensions.rb +12 -31
- data/lib/squeel/adapters/active_record/3.1/context.rb +4 -4
- data/lib/squeel/adapters/active_record/3.1/relation_extensions.rb +12 -21
- data/lib/squeel/adapters/active_record/relation_extensions.rb +4 -4
- data/lib/squeel/dsl.rb +1 -2
- data/lib/squeel/version.rb +1 -1
- data/lib/squeel/visitors/attribute_visitor.rb +13 -9
- data/lib/squeel/visitors/predicate_visitor.rb +21 -17
- data/lib/squeel/visitors/visitor.rb +11 -0
- data/spec/squeel/adapters/active_record/relation_extensions_spec.rb +9 -0
- data/spec/squeel/visitors/predicate_visitor_spec.rb +15 -7
- metadata +4 -4
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
## 1.0.3 (2012-06-07)
|
2
|
+
|
3
|
+
* Port fix for Rails CVE-2012-2661 to Squeel.
|
4
|
+
* Reduce risk of a potential memory leak through overzealous
|
5
|
+
calling to to_sym.
|
6
|
+
* Allow right-hand relation conditions to prevail in Relation#merge.
|
7
|
+
|
8
|
+
## 1.0.2 (2012-05-30)
|
3
9
|
|
4
10
|
* Add groupings to DSL. Allows control of matched sets of
|
5
11
|
parentheses in the absence of not/and/etc. Accessed via
|
@@ -9,12 +15,10 @@
|
|
9
15
|
* Work around issue with Relation#count when where_values
|
10
16
|
contains InfixOperations. Fixes #122.
|
11
17
|
|
12
|
-
|
13
|
-
## 2012-05-02
|
18
|
+
## 1.0.1 (2012-05-02)
|
14
19
|
|
15
20
|
* Undefine `type` method on Stubs/KeyPaths for 1.8.x compat.
|
16
21
|
|
17
|
-
|
18
|
-
## 2012-04-22
|
22
|
+
## 1.0.0 (2012-04-22)
|
19
23
|
|
20
24
|
* Official 1.0.0 release.
|
@@ -17,11 +17,11 @@ module Squeel
|
|
17
17
|
|
18
18
|
def find(object, parent = @base)
|
19
19
|
if JoinBase === parent
|
20
|
-
object = object.to_sym if String === object
|
21
20
|
case object
|
22
|
-
when Symbol, Nodes::Stub
|
21
|
+
when String, Symbol, Nodes::Stub
|
22
|
+
assoc_name = object.to_s
|
23
23
|
@object.join_associations.detect { |j|
|
24
|
-
j.reflection.name ==
|
24
|
+
j.reflection.name.to_s == assoc_name && j.parent == parent
|
25
25
|
}
|
26
26
|
when Nodes::Join
|
27
27
|
@object.join_associations.detect { |j|
|
@@ -50,7 +50,7 @@ module Squeel
|
|
50
50
|
|
51
51
|
def get_table(object)
|
52
52
|
if [Symbol, String, Nodes::Stub].include?(object.class)
|
53
|
-
Arel::Table.new(object.
|
53
|
+
Arel::Table.new(object.to_s, :engine => @engine)
|
54
54
|
elsif Nodes::Join === object
|
55
55
|
object._klass ? object._klass.arel_table : Arel::Table.new(object._name, :engine => @engine)
|
56
56
|
elsif object.respond_to?(:aliased_table_name)
|
@@ -32,38 +32,19 @@ module Squeel
|
|
32
32
|
)
|
33
33
|
end
|
34
34
|
|
35
|
-
# We need to be able to support merging two relations
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
if relation_with_different_base?(r)
|
48
|
-
r = r.clone.visit!
|
35
|
+
# We need to be able to support merging two relations without having
|
36
|
+
# to get our hooks too deeply into ActiveRecord. AR's relation
|
37
|
+
# merge functionality is very cool, but relatively complex, to
|
38
|
+
# handle the various edge cases. Our best shot at avoiding strange
|
39
|
+
# behavior with Squeel loaded is to visit the *_values arrays in
|
40
|
+
# the relations we're merging, and then use the default AR merge
|
41
|
+
# code on the result.
|
42
|
+
def merge(r, relations_visited = false)
|
43
|
+
if relations_visited
|
44
|
+
super(r)
|
45
|
+
else
|
46
|
+
clone.visit!.merge(r.clone.visit!, true)
|
49
47
|
end
|
50
|
-
|
51
|
-
super(r)
|
52
|
-
end
|
53
|
-
|
54
|
-
def relation_with_different_base?(r)
|
55
|
-
::ActiveRecord::Relation === r &&
|
56
|
-
base_class.name != r.klass.base_class.name
|
57
|
-
end
|
58
|
-
|
59
|
-
def prepare_relation_for_association_merge!(r, association_name)
|
60
|
-
r.where_values.map! {|w| Squeel::Visitors::PredicateVisitor.can_visit?(w) ? {association_name => w} : w}
|
61
|
-
r.having_values.map! {|h| Squeel::Visitors::PredicateVisitor.can_visit?(h) ? {association_name => h} : h}
|
62
|
-
r.group_values.map! {|g| Squeel::Visitors::AttributeVisitor.can_visit?(g) ? {association_name => g} : g}
|
63
|
-
r.order_values.map! {|o| Squeel::Visitors::AttributeVisitor.can_visit?(o) ? {association_name => o} : o}
|
64
|
-
r.select_values.map! {|s| Squeel::Visitors::AttributeVisitor.can_visit?(s) ? {association_name => s} : s}
|
65
|
-
r.joins_values.map! {|j| [Symbol, Hash, Nodes::Stub, Nodes::Join, Nodes::KeyPath].include?(j.class) ? {association_name => j} : j}
|
66
|
-
r.includes_values.map! {|i| [Symbol, Hash, Nodes::Stub, Nodes::Join, Nodes::KeyPath].include?(i.class) ? {association_name => i} : i}
|
67
48
|
end
|
68
49
|
|
69
50
|
def visit!
|
@@ -17,11 +17,11 @@ module Squeel
|
|
17
17
|
|
18
18
|
def find(object, parent = @base)
|
19
19
|
if JoinPart === parent
|
20
|
-
object = object.to_sym if String === object
|
21
20
|
case object
|
22
|
-
when Symbol, Nodes::Stub
|
21
|
+
when String, Symbol, Nodes::Stub
|
22
|
+
assoc_name = object.to_s
|
23
23
|
@object.join_associations.detect { |j|
|
24
|
-
j.reflection.name ==
|
24
|
+
j.reflection.name.to_s == assoc_name && j.parent == parent
|
25
25
|
}
|
26
26
|
when Nodes::Join
|
27
27
|
@object.join_associations.detect { |j|
|
@@ -50,7 +50,7 @@ module Squeel
|
|
50
50
|
|
51
51
|
def get_table(object)
|
52
52
|
if [Symbol, String, Nodes::Stub].include?(object.class)
|
53
|
-
Arel::Table.new(object.
|
53
|
+
Arel::Table.new(object.to_s, :engine => @engine)
|
54
54
|
elsif Nodes::Join === object
|
55
55
|
object._klass ? object._klass.arel_table : Arel::Table.new(object._name, :engine => @engine)
|
56
56
|
elsif object.respond_to?(:aliased_table_name)
|
@@ -32,28 +32,19 @@ module Squeel
|
|
32
32
|
)
|
33
33
|
end
|
34
34
|
|
35
|
-
# We need to be able to support merging two relations
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
if relation_with_different_base?(r)
|
48
|
-
r = r.clone.visit!
|
35
|
+
# We need to be able to support merging two relations without having
|
36
|
+
# to get our hooks too deeply into ActiveRecord. AR's relation
|
37
|
+
# merge functionality is very cool, but relatively complex, to
|
38
|
+
# handle the various edge cases. Our best shot at avoiding strange
|
39
|
+
# behavior with Squeel loaded is to visit the *_values arrays in
|
40
|
+
# the relations we're merging, and then use the default AR merge
|
41
|
+
# code on the result.
|
42
|
+
def merge(r, relations_visited = false)
|
43
|
+
if relations_visited
|
44
|
+
super(r)
|
45
|
+
else
|
46
|
+
clone.visit!.merge(r.clone.visit!, true)
|
49
47
|
end
|
50
|
-
|
51
|
-
super(r)
|
52
|
-
end
|
53
|
-
|
54
|
-
def relation_with_different_base?(r)
|
55
|
-
::ActiveRecord::Relation === r &&
|
56
|
-
base_class.name != r.klass.base_class.name
|
57
48
|
end
|
58
49
|
|
59
50
|
def prepare_relation_for_association_merge!(r, association_name)
|
@@ -4,7 +4,7 @@ module Squeel
|
|
4
4
|
module Adapters
|
5
5
|
module ActiveRecord
|
6
6
|
module RelationExtensions
|
7
|
-
|
7
|
+
|
8
8
|
def build_arel
|
9
9
|
arel = table.from table
|
10
10
|
|
@@ -28,15 +28,15 @@ module Squeel
|
|
28
28
|
arel.order(*order) unless order.empty?
|
29
29
|
|
30
30
|
build_select(arel, attribute_viz.accept(@select_values.uniq))
|
31
|
-
|
31
|
+
|
32
32
|
arel.distinct(@uniq_value)
|
33
33
|
arel.from(@from_value) if @from_value
|
34
34
|
arel.lock(@lock_value) if @lock_value
|
35
35
|
|
36
36
|
arel
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
42
|
-
end
|
42
|
+
end
|
data/lib/squeel/dsl.rb
CHANGED
@@ -86,8 +86,7 @@ module Squeel
|
|
86
86
|
# @param [Symbol, Nodes::Stub] name The name of the sifter defined in the model.
|
87
87
|
# @return [Nodes::Sifter] The sifter node
|
88
88
|
def sift(name, *args)
|
89
|
-
|
90
|
-
Nodes::Sifter.new name, args
|
89
|
+
Nodes::Sifter.new name.to_sym, args
|
91
90
|
end
|
92
91
|
|
93
92
|
# Node generation inside DSL blocks.
|
data/lib/squeel/version.rb
CHANGED
@@ -16,10 +16,10 @@ module Squeel
|
|
16
16
|
# @return [Array] An array of values for use in an ordering, grouping, etc.
|
17
17
|
def visit_Hash(o, parent)
|
18
18
|
o.map do |k, v|
|
19
|
-
if
|
20
|
-
|
19
|
+
if implies_hash_context_shift?(v)
|
20
|
+
visit_with_hash_context_shift(k, v, parent)
|
21
21
|
else
|
22
|
-
|
22
|
+
visit_without_hash_context_shift(k, v, parent)
|
23
23
|
end
|
24
24
|
end.flatten
|
25
25
|
end
|
@@ -41,7 +41,7 @@ module Squeel
|
|
41
41
|
# @param parent The stub's parent within the context
|
42
42
|
# @return [Arel::Attribute] An attribute on the contextualized parent table
|
43
43
|
def visit_Squeel_Nodes_Stub(o, parent)
|
44
|
-
contextualize(parent)[o.
|
44
|
+
contextualize(parent)[o.to_s]
|
45
45
|
end
|
46
46
|
|
47
47
|
# Visit a Literal by converting it to an ARel SqlLiteral
|
@@ -94,7 +94,7 @@ module Squeel
|
|
94
94
|
when Nodes::Function, Nodes::KeyPath, Nodes::As, Nodes::Literal, Nodes::Grouping
|
95
95
|
visit(arg, parent)
|
96
96
|
when Symbol, Nodes::Stub
|
97
|
-
Arel.sql(arel_visitor.accept contextualize(parent)[arg.
|
97
|
+
Arel.sql(arel_visitor.accept contextualize(parent)[arg.to_s])
|
98
98
|
else
|
99
99
|
quote arg
|
100
100
|
end
|
@@ -116,7 +116,7 @@ module Squeel
|
|
116
116
|
when Nodes::Function, Nodes::KeyPath, Nodes::As, Nodes::Literal, Nodes::Grouping
|
117
117
|
visit(arg, parent)
|
118
118
|
when Symbol, Nodes::Stub
|
119
|
-
Arel.sql(arel_visitor.accept contextualize(parent)[arg.
|
119
|
+
Arel.sql(arel_visitor.accept contextualize(parent)[arg.to_s])
|
120
120
|
else
|
121
121
|
quote arg
|
122
122
|
end
|
@@ -166,7 +166,7 @@ module Squeel
|
|
166
166
|
|
167
167
|
# @return [Boolean] Whether the given value implies a context change
|
168
168
|
# @param v The value to consider
|
169
|
-
def
|
169
|
+
def implies_hash_context_shift?(v)
|
170
170
|
can_visit?(v)
|
171
171
|
end
|
172
172
|
|
@@ -177,7 +177,9 @@ module Squeel
|
|
177
177
|
# @param v The hash value
|
178
178
|
# @param parent The current parent object in the context
|
179
179
|
# @return The visited value
|
180
|
-
def
|
180
|
+
def visit_with_hash_context_shift(k, v, parent)
|
181
|
+
@hash_context_depth += 1
|
182
|
+
|
181
183
|
parent = case k
|
182
184
|
when Nodes::KeyPath
|
183
185
|
traverse(k, parent, true)
|
@@ -190,6 +192,8 @@ module Squeel
|
|
190
192
|
else
|
191
193
|
can_visit?(v) ? visit(v, parent || k) : v
|
192
194
|
end
|
195
|
+
ensure
|
196
|
+
@hash_context_depth -= 1
|
193
197
|
end
|
194
198
|
|
195
199
|
# If there is no context change, we'll just return the value unchanged,
|
@@ -201,7 +205,7 @@ module Squeel
|
|
201
205
|
# @param parent The current parent object in the context
|
202
206
|
# @return The same value we just received. Yeah, this method's pretty pointless,
|
203
207
|
# for now, and only here for consistency's sake.
|
204
|
-
def
|
208
|
+
def visit_without_hash_context_shift(k, v, parent)
|
205
209
|
v
|
206
210
|
end
|
207
211
|
|
@@ -17,10 +17,10 @@ module Squeel
|
|
17
17
|
# @return [Array] An array of values for use in a where or having clause
|
18
18
|
def visit_Hash(o, parent)
|
19
19
|
predicates = o.map do |k, v|
|
20
|
-
if
|
21
|
-
|
20
|
+
if implies_hash_context_shift?(v)
|
21
|
+
visit_with_hash_context_shift(k, v, parent)
|
22
22
|
else
|
23
|
-
|
23
|
+
visit_without_hash_context_shift(k, v, parent)
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -71,7 +71,7 @@ module Squeel
|
|
71
71
|
# @return [Arel::Attribute] An attribute of the parent table with the
|
72
72
|
# Stub's column
|
73
73
|
def visit_Squeel_Nodes_Stub(o, parent)
|
74
|
-
contextualize(parent)[o.
|
74
|
+
contextualize(parent)[o.to_s]
|
75
75
|
end
|
76
76
|
|
77
77
|
# Visit a Literal by converting it to an ARel SqlLiteral
|
@@ -105,7 +105,7 @@ module Squeel
|
|
105
105
|
|
106
106
|
case value
|
107
107
|
when Nodes::KeyPath
|
108
|
-
value = can_visit?(value.endpoint) ? visit(value, parent) : contextualize(traverse(value, parent))[value.endpoint.
|
108
|
+
value = can_visit?(value.endpoint) ? visit(value, parent) : contextualize(traverse(value, parent))[value.endpoint.to_s]
|
109
109
|
when ActiveRecord::Relation
|
110
110
|
value = visit(
|
111
111
|
value.select_values.empty? ? value.select(value.klass.arel_table[value.klass.primary_key]) : value,
|
@@ -145,9 +145,9 @@ module Squeel
|
|
145
145
|
when ActiveRecord::Relation
|
146
146
|
arg.arel.ast
|
147
147
|
when Nodes::KeyPath
|
148
|
-
can_visit?(arg.endpoint) ? visit(arg, parent) : contextualize(traverse(arg, parent))[arg.endpoint.
|
148
|
+
can_visit?(arg.endpoint) ? visit(arg, parent) : contextualize(traverse(arg, parent))[arg.endpoint.to_s]
|
149
149
|
when Symbol, Nodes::Stub
|
150
|
-
Arel.sql(arel_visitor.accept contextualize(parent)[arg.
|
150
|
+
Arel.sql(arel_visitor.accept contextualize(parent)[arg.to_s])
|
151
151
|
else
|
152
152
|
quote arg
|
153
153
|
end
|
@@ -179,9 +179,9 @@ module Squeel
|
|
179
179
|
when Nodes::Function, Nodes::As, Nodes::Literal, Nodes::Grouping
|
180
180
|
visit(arg, parent)
|
181
181
|
when Nodes::KeyPath
|
182
|
-
can_visit?(arg.endpoint) ? visit(arg, parent) : contextualize(traverse(arg, parent))[arg.endpoint.
|
182
|
+
can_visit?(arg.endpoint) ? visit(arg, parent) : contextualize(traverse(arg, parent))[arg.endpoint.to_s]
|
183
183
|
when Symbol, Nodes::Stub
|
184
|
-
Arel.sql(arel_visitor.accept contextualize(parent)[arg.
|
184
|
+
Arel.sql(arel_visitor.accept contextualize(parent)[arg.to_s])
|
185
185
|
else
|
186
186
|
quote arg
|
187
187
|
end
|
@@ -252,7 +252,7 @@ module Squeel
|
|
252
252
|
|
253
253
|
# @return [Boolean] Whether the given value implies a context change
|
254
254
|
# @param v The value to consider
|
255
|
-
def
|
255
|
+
def implies_hash_context_shift?(v)
|
256
256
|
case v
|
257
257
|
when Hash, Nodes::Predicate, Nodes::Unary, Nodes::Binary, Nodes::Nary, Nodes::Sifter
|
258
258
|
true
|
@@ -270,7 +270,9 @@ module Squeel
|
|
270
270
|
# @param v The hash value
|
271
271
|
# @param parent The current parent object in the context
|
272
272
|
# @return The visited value
|
273
|
-
def
|
273
|
+
def visit_with_hash_context_shift(k, v, parent)
|
274
|
+
@hash_context_depth += 1
|
275
|
+
|
274
276
|
parent = case k
|
275
277
|
when Nodes::KeyPath
|
276
278
|
traverse(k, parent, true)
|
@@ -290,6 +292,8 @@ module Squeel
|
|
290
292
|
of key = #{k} and value = #{v}"
|
291
293
|
END
|
292
294
|
end
|
295
|
+
ensure
|
296
|
+
@hash_context_depth -= 1
|
293
297
|
end
|
294
298
|
|
295
299
|
# Create a predicate for a given key/value pair. If the value is
|
@@ -300,12 +304,12 @@ module Squeel
|
|
300
304
|
# @param v The hash value
|
301
305
|
# @param parent The current parent object in the context
|
302
306
|
# @return An ARel predicate
|
303
|
-
def
|
307
|
+
def visit_without_hash_context_shift(k, v, parent)
|
304
308
|
case v
|
305
309
|
when Nodes::Stub, Symbol
|
306
|
-
v = contextualize(parent)[v.
|
310
|
+
v = contextualize(parent)[v.to_s]
|
307
311
|
when Nodes::KeyPath # If we could visit the endpoint, we wouldn't be here
|
308
|
-
v = contextualize(traverse(v, parent))[v.endpoint.
|
312
|
+
v = contextualize(traverse(v, parent))[v.endpoint.to_s]
|
309
313
|
end
|
310
314
|
|
311
315
|
case k
|
@@ -317,11 +321,11 @@ module Squeel
|
|
317
321
|
visit(k % quote_for_node(k.endpoint, v), parent)
|
318
322
|
else
|
319
323
|
attr_name = k.to_s
|
320
|
-
attribute = if attr_name.include?('.')
|
324
|
+
attribute = if !hash_context_shifted? && attr_name.include?('.')
|
321
325
|
table_name, attr_name = attr_name.split(/\./, 2)
|
322
|
-
Arel::Table.new(table_name.
|
326
|
+
Arel::Table.new(table_name.to_s, :engine => engine)[attr_name.to_s]
|
323
327
|
else
|
324
|
-
contextualize(parent)[
|
328
|
+
contextualize(parent)[attr_name]
|
325
329
|
end
|
326
330
|
arel_predicate_for(attribute, v, parent)
|
327
331
|
end
|
@@ -14,6 +14,7 @@ module Squeel
|
|
14
14
|
# @param [Context] context The context to use for node visitation.
|
15
15
|
def initialize(context = nil)
|
16
16
|
@context = context
|
17
|
+
@hash_context_depth = 0
|
17
18
|
end
|
18
19
|
|
19
20
|
# Accept an object.
|
@@ -50,6 +51,16 @@ module Squeel
|
|
50
51
|
hash[klass] = "visit_#{(klass.name || '').gsub('::', '_')}"
|
51
52
|
end
|
52
53
|
|
54
|
+
# If we're visiting stuff in a hash, it's good to check whether or
|
55
|
+
# not we've shifted context already. If we have, we may want to use
|
56
|
+
# caution as it pertains to certain input, in case it's untrusted.
|
57
|
+
# See CVE-2012-2661 for info.
|
58
|
+
#
|
59
|
+
# @return [Boolean] Whether we're within a new context.
|
60
|
+
def hash_context_shifted?
|
61
|
+
@hash_context_depth > 0
|
62
|
+
end
|
63
|
+
|
53
64
|
# Important to avoid accidentally allowing the default ARel visitor's
|
54
65
|
# last_column quoting behavior (where a value is quoted as though it
|
55
66
|
# is of the type of the last visited column). This can wreak havoc with
|
@@ -672,6 +672,15 @@ module Squeel
|
|
672
672
|
sql.should match /"articles"."title" = 'Condition'/
|
673
673
|
end
|
674
674
|
|
675
|
+
it 'uses the last condition in the case of a conflicting where' do
|
676
|
+
relation = Person.where{name == 'Ernie'}.merge(
|
677
|
+
Person.where{name == 'Bert'}
|
678
|
+
)
|
679
|
+
sql = relation.to_sql
|
680
|
+
sql.should_not match /Ernie/
|
681
|
+
sql.should match /Bert/
|
682
|
+
end
|
683
|
+
|
675
684
|
end
|
676
685
|
|
677
686
|
describe '#to_a' do
|
@@ -26,14 +26,14 @@ module Squeel
|
|
26
26
|
it 'creates Equality nodes for simple hashes' do
|
27
27
|
predicate = @v.accept(:name => 'Joe')
|
28
28
|
predicate.should be_a Arel::Nodes::Equality
|
29
|
-
predicate.left.name.should eq
|
29
|
+
predicate.left.name.to_s.should eq 'name'
|
30
30
|
predicate.right.should eq 'Joe'
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'creates In nodes for simple hashes with an array as a value' do
|
34
34
|
predicate = @v.accept(:name => ['Joe', 'Bob'])
|
35
35
|
predicate.should be_a Arel::Nodes::In
|
36
|
-
predicate.left.name.should eq
|
36
|
+
predicate.left.name.to_s.should eq 'name'
|
37
37
|
predicate.right.should eq ['Joe', 'Bob']
|
38
38
|
end
|
39
39
|
|
@@ -112,14 +112,14 @@ module Squeel
|
|
112
112
|
it 'allows a subquery on the value side of an explicit predicate' do
|
113
113
|
predicate = @v.accept dsl{name.in(Person.select{name}.where{name.in(['Aric Smith', 'Gladyce Kulas'])})}
|
114
114
|
predicate.should be_a Arel::Nodes::In
|
115
|
-
predicate.left.name.should eq
|
115
|
+
predicate.left.name.to_s.should eq 'name'
|
116
116
|
predicate.right.should be_a Arel::Nodes::SelectStatement
|
117
117
|
end
|
118
118
|
|
119
119
|
it 'allows a subquery on the value side of an implicit predicate' do
|
120
120
|
predicate = @v.accept(:name => Person.select{name}.where{name.in(['Aric Smith', 'Gladyce Kulas'])})
|
121
121
|
predicate.should be_a Arel::Nodes::In
|
122
|
-
predicate.left.name.should eq
|
122
|
+
predicate.left.name.to_s.should eq 'name'
|
123
123
|
predicate.right.should be_a Arel::Nodes::SelectStatement
|
124
124
|
end
|
125
125
|
|
@@ -150,14 +150,14 @@ module Squeel
|
|
150
150
|
it 'converts ActiveRecord::Base objects to their id' do
|
151
151
|
predicate = @v.accept(:id => Person.first)
|
152
152
|
predicate.should be_a Arel::Nodes::Equality
|
153
|
-
predicate.left.name.should eq
|
153
|
+
predicate.left.name.to_s.should eq 'id'
|
154
154
|
predicate.right.should eq 1
|
155
155
|
end
|
156
156
|
|
157
157
|
it 'converts arrays of ActiveRecord::Base objects to their ids' do
|
158
158
|
predicate = @v.accept(:id => [Person.first, Person.last])
|
159
159
|
predicate.should be_a Arel::Nodes::In
|
160
|
-
predicate.left.name.should eq
|
160
|
+
predicate.left.name.to_s.should eq 'id'
|
161
161
|
predicate.right.should eq [1, 332]
|
162
162
|
end
|
163
163
|
|
@@ -305,6 +305,14 @@ module Squeel
|
|
305
305
|
predicate.to_sql.should match /"things"."attribute" = 'retro'/
|
306
306
|
end
|
307
307
|
|
308
|
+
it 'does not allow "table.column" keys after context change' do
|
309
|
+
result = @v.accept(:id => {'articles.person_id' => 1})
|
310
|
+
result.should be_a Arel::Nodes::Equality
|
311
|
+
result.left.should be_a Arel::Attributes::Attribute
|
312
|
+
result.left.relation.name.should eq 'id'
|
313
|
+
result.left.name.to_s.should eq 'articles.person_id'
|
314
|
+
end
|
315
|
+
|
308
316
|
it 'visits ActiveRecord::Relation values in predicates' do
|
309
317
|
predicate = @v.accept(dsl{id >> Person.select{id}.limit(3).order{id.desc}})
|
310
318
|
predicate.should be_a Arel::Nodes::In
|
@@ -367,7 +375,7 @@ module Squeel
|
|
367
375
|
predicate = @v.accept(:children => Nodes::Stub.new(:children).name.eq('Joe'))
|
368
376
|
predicate.should be_a Arel::Nodes::Equality
|
369
377
|
predicate.left.relation.table_alias.should eq 'children_people_2'
|
370
|
-
predicate.left.name.should eq
|
378
|
+
predicate.left.name.to_s.should eq 'name'
|
371
379
|
predicate.right.should eq 'Joe'
|
372
380
|
end
|
373
381
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: squeel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-06-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -240,7 +240,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
240
240
|
version: '0'
|
241
241
|
segments:
|
242
242
|
- 0
|
243
|
-
hash: -
|
243
|
+
hash: -3464922984987800394
|
244
244
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
245
245
|
none: false
|
246
246
|
requirements:
|
@@ -249,7 +249,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
249
249
|
version: '0'
|
250
250
|
segments:
|
251
251
|
- 0
|
252
|
-
hash: -
|
252
|
+
hash: -3464922984987800394
|
253
253
|
requirements: []
|
254
254
|
rubyforge_project: squeel
|
255
255
|
rubygems_version: 1.8.24
|