squeel 1.0.2 → 1.0.3
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/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
|