squeel 0.8.6 → 0.8.7
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/lib/squeel/adapters/active_record/3.0/relation.rb +21 -13
- data/lib/squeel/adapters/active_record/relation.rb +22 -13
- data/lib/squeel/nodes/binary.rb +3 -3
- data/lib/squeel/nodes/join.rb +4 -4
- data/lib/squeel/nodes/key_path.rb +4 -3
- data/lib/squeel/nodes/literal.rb +2 -2
- data/lib/squeel/nodes/nary.rb +7 -2
- data/lib/squeel/nodes/stub.rb +2 -2
- data/lib/squeel/nodes/unary.rb +2 -2
- data/lib/squeel/version.rb +1 -1
- data/spec/squeel/adapters/active_record/relation_spec.rb +10 -1
- data/spec/squeel/visitors/predicate_visitor_spec.rb +1 -1
- data/spec/support/schema.rb +14 -0
- metadata +15 -17
@@ -38,14 +38,14 @@ module Squeel
|
|
38
38
|
# already bound to the proper table.
|
39
39
|
#
|
40
40
|
# Squeel, on the other hand, needs to do its best to ensure the predicates are still
|
41
|
-
# winding up against the proper table.
|
42
|
-
#
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
41
|
+
# winding up against the proper table. The most "correct" way I can think of to do
|
42
|
+
# this is to try to emulate the default AR behavior -- that is, de-squeelifying
|
43
|
+
# the *_values, erm... values by visiting them and converting them to ARel nodes
|
44
|
+
# before merging. Merging relations is a nifty little trick, but it's another
|
45
|
+
# little corner of ActiveRecord where the magic quickly fades. :(
|
46
|
+
def merge(r)
|
47
|
+
if relation_with_different_base?(r)
|
48
|
+
r = r.clone.visit!
|
49
49
|
end
|
50
50
|
|
51
51
|
super(r)
|
@@ -56,11 +56,6 @@ module Squeel
|
|
56
56
|
base_class.name != r.klass.base_class.name
|
57
57
|
end
|
58
58
|
|
59
|
-
def infer_association_for_relation_merge(r)
|
60
|
-
default_association = reflect_on_all_associations.detect {|a| a.class_name == r.klass.name}
|
61
|
-
default_association ? default_association.name : r.table_name.to_sym
|
62
|
-
end
|
63
|
-
|
64
59
|
def prepare_relation_for_association_merge!(r, association_name)
|
65
60
|
r.where_values.map! {|w| Squeel::Visitors::PredicateVisitor.can_visit?(w) ? {association_name => w} : w}
|
66
61
|
r.having_values.map! {|h| Squeel::Visitors::PredicateVisitor.can_visit?(h) ? {association_name => h} : h}
|
@@ -71,6 +66,19 @@ module Squeel
|
|
71
66
|
r.includes_values.map! {|i| [Symbol, Hash, Nodes::Stub, Nodes::Join, Nodes::KeyPath].include?(i.class) ? {association_name => i} : i}
|
72
67
|
end
|
73
68
|
|
69
|
+
def visit!
|
70
|
+
predicate_viz = predicate_visitor
|
71
|
+
attribute_viz = attribute_visitor
|
72
|
+
|
73
|
+
@where_values = predicate_viz.accept((@where_values - ['']).uniq)
|
74
|
+
@having_values = predicate_viz.accept(@having_values.uniq.reject{|h| h.blank?})
|
75
|
+
@group_values = attribute_viz.accept(@group_values.uniq.reject{|g| g.blank?})
|
76
|
+
@order_values = attribute_viz.accept(@order_values.uniq.reject{|o| o.blank?})
|
77
|
+
@select_values = attribute_viz.accept(@select_values.uniq)
|
78
|
+
|
79
|
+
self
|
80
|
+
end
|
81
|
+
|
74
82
|
def build_arel
|
75
83
|
arel = table
|
76
84
|
|
@@ -38,13 +38,14 @@ module Squeel
|
|
38
38
|
# already bound to the proper table.
|
39
39
|
#
|
40
40
|
# Squeel, on the other hand, needs to do its best to ensure the predicates are still
|
41
|
-
# winding up against the proper table.
|
42
|
-
#
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
41
|
+
# winding up against the proper table. The most "correct" way I can think of to do
|
42
|
+
# this is to try to emulate the default AR behavior -- that is, de-squeelifying
|
43
|
+
# the *_values, erm... values by visiting them and converting them to ARel nodes
|
44
|
+
# before merging. Merging relations is a nifty little trick, but it's another
|
45
|
+
# little corner of ActiveRecord where the magic quickly fades. :(
|
46
|
+
def merge(r)
|
47
|
+
if relation_with_different_base?(r)
|
48
|
+
r = r.clone.visit!
|
48
49
|
end
|
49
50
|
|
50
51
|
super(r)
|
@@ -55,11 +56,6 @@ module Squeel
|
|
55
56
|
base_class.name != r.klass.base_class.name
|
56
57
|
end
|
57
58
|
|
58
|
-
def infer_association_for_relation_merge(r)
|
59
|
-
default_association = reflect_on_all_associations.detect {|a| a.class_name == r.klass.name}
|
60
|
-
default_association ? default_association.name : r.table_name.to_sym
|
61
|
-
end
|
62
|
-
|
63
59
|
def prepare_relation_for_association_merge!(r, association_name)
|
64
60
|
r.where_values.map! {|w| Squeel::Visitors::PredicateVisitor.can_visit?(w) ? {association_name => w} : w}
|
65
61
|
r.having_values.map! {|h| Squeel::Visitors::PredicateVisitor.can_visit?(h) ? {association_name => h} : h}
|
@@ -70,6 +66,19 @@ module Squeel
|
|
70
66
|
r.includes_values.map! {|i| [Symbol, Hash, Nodes::Stub, Nodes::Join, Nodes::KeyPath].include?(i.class) ? {association_name => i} : i}
|
71
67
|
end
|
72
68
|
|
69
|
+
def visit!
|
70
|
+
predicate_viz = predicate_visitor
|
71
|
+
attribute_viz = attribute_visitor
|
72
|
+
|
73
|
+
@where_values = predicate_viz.accept((@where_values - ['']).uniq)
|
74
|
+
@having_values = predicate_viz.accept(@having_values.uniq.reject{|h| h.blank?})
|
75
|
+
@group_values = attribute_viz.accept(@group_values.uniq.reject{|g| g.blank?})
|
76
|
+
@order_values = attribute_viz.accept(@order_values.uniq.reject{|o| o.blank?})
|
77
|
+
@select_values = attribute_viz.accept(@select_values.uniq)
|
78
|
+
|
79
|
+
self
|
80
|
+
end
|
81
|
+
|
73
82
|
def build_arel
|
74
83
|
arel = table.from table
|
75
84
|
|
@@ -263,7 +272,7 @@ module Squeel
|
|
263
272
|
end
|
264
273
|
|
265
274
|
def collapse_wheres(arel, wheres)
|
266
|
-
wheres =
|
275
|
+
wheres = Array(wheres)
|
267
276
|
binaries = wheres.grep(Arel::Nodes::Binary)
|
268
277
|
|
269
278
|
groups = binaries.group_by {|b| [b.class, b.left]}
|
data/lib/squeel/nodes/binary.rb
CHANGED
@@ -21,9 +21,9 @@ module Squeel
|
|
21
21
|
|
22
22
|
# Comparison with other nodes
|
23
23
|
def eql?(other)
|
24
|
-
self.class
|
25
|
-
self.left
|
26
|
-
self.right
|
24
|
+
self.class.eql?(other.class) &&
|
25
|
+
self.left.eql?(other.left) &&
|
26
|
+
self.right.eql?(other.right)
|
27
27
|
end
|
28
28
|
alias :== :eql?
|
29
29
|
|
data/lib/squeel/nodes/join.rb
CHANGED
@@ -52,10 +52,10 @@ module Squeel
|
|
52
52
|
|
53
53
|
# Compare with other objects
|
54
54
|
def eql?(other)
|
55
|
-
self.class
|
56
|
-
self._name
|
57
|
-
self._type
|
58
|
-
self._klass
|
55
|
+
self.class.eql?(other.class) &&
|
56
|
+
self._name.eql?(other._name) &&
|
57
|
+
self._type.eql?(other._type) &&
|
58
|
+
self._klass.eql?(other._klass)
|
59
59
|
end
|
60
60
|
alias :== :eql?
|
61
61
|
|
@@ -42,10 +42,10 @@ module Squeel
|
|
42
42
|
|
43
43
|
# Object comparison
|
44
44
|
def eql?(other)
|
45
|
-
self.class
|
46
|
-
self.path
|
45
|
+
self.class.eql?(other.class) &&
|
46
|
+
self.path.eql?(other.path) &&
|
47
47
|
self.endpoint.eql?(other.endpoint) &&
|
48
|
-
self.absolute?
|
48
|
+
self.absolute?.eql?(other.absolute?)
|
49
49
|
end
|
50
50
|
|
51
51
|
# Allow KeyPath to function like its endpoint, in the case where its endpoint
|
@@ -161,6 +161,7 @@ module Squeel
|
|
161
161
|
# @return [KeyPath] The updated KeyPath
|
162
162
|
def method_missing(method_id, *args)
|
163
163
|
super if method_id == :to_ary
|
164
|
+
|
164
165
|
if endpoint.respond_to? method_id
|
165
166
|
@endpoint = @endpoint.send(method_id, *args)
|
166
167
|
self
|
data/lib/squeel/nodes/literal.rb
CHANGED
data/lib/squeel/nodes/nary.rb
CHANGED
@@ -33,10 +33,15 @@ module Squeel
|
|
33
33
|
self
|
34
34
|
end
|
35
35
|
|
36
|
+
# Implemented for equality testing
|
37
|
+
def hash
|
38
|
+
[self.class].concat(self.children).hash
|
39
|
+
end
|
40
|
+
|
36
41
|
# Object comparison
|
37
42
|
def eql?(other)
|
38
|
-
self.class
|
39
|
-
self.children
|
43
|
+
self.class.eql?(other.class) &&
|
44
|
+
self.children.eql?(other.children)
|
40
45
|
end
|
41
46
|
alias :== :eql?
|
42
47
|
|
data/lib/squeel/nodes/stub.rb
CHANGED
data/lib/squeel/nodes/unary.rb
CHANGED
data/lib/squeel/version.rb
CHANGED
@@ -189,6 +189,15 @@ module Squeel
|
|
189
189
|
arel.to_sql.should match /ORDER BY "parents_people_2"."id" ASC/
|
190
190
|
end
|
191
191
|
|
192
|
+
it 'does not inadvertently convert KeyPaths to booleans when uniqing where_values' do
|
193
|
+
100.times do # Doesn't happen reliably because of #hash behavior
|
194
|
+
persons = Person.joins{[outgoing_messages.outer, incoming_messages.outer]}
|
195
|
+
persons = persons.where { (outgoing_messages.author_id.not_eq 7) & (incoming_messages.author_id.not_eq 7) }
|
196
|
+
persons = persons.where{(outgoing_messages.recipient_id.not_eq 7) & (incoming_messages.recipient_id.not_eq 7)}
|
197
|
+
expect { persons.to_sql }.not_to raise_error TypeError
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
192
201
|
end
|
193
202
|
|
194
203
|
describe '#to_sql' do
|
@@ -616,7 +625,7 @@ module Squeel
|
|
616
625
|
end
|
617
626
|
|
618
627
|
it 'merges relations with a different base' do
|
619
|
-
relation = Person.where{name == 'bob'}.joins(:articles).merge(Article.where{title == 'Hello world!'}
|
628
|
+
relation = Person.where{name == 'bob'}.joins(:articles).merge(Article.where{title == 'Hello world!'})
|
620
629
|
sql = relation.to_sql
|
621
630
|
sql.should match /INNER JOIN "articles" ON "articles"."person_id" = "people"."id"/
|
622
631
|
sql.should match /"people"."name" = 'bob'/
|
data/spec/support/schema.rb
CHANGED
@@ -16,6 +16,15 @@ class Person < ActiveRecord::Base
|
|
16
16
|
:source => :comments
|
17
17
|
has_many :notes, :as => :notable
|
18
18
|
has_many :unidentified_objects
|
19
|
+
|
20
|
+
has_many :outgoing_messages, :class_name => 'Message', :foreign_key => :author_id
|
21
|
+
has_many :incoming_messages, :class_name => 'Message', :foreign_key => :recipient_id
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
class Message < ActiveRecord::Base
|
26
|
+
belongs_to :author, :class_name => 'Person'
|
27
|
+
belongs_to :recipient, :class_name => 'Person'
|
19
28
|
end
|
20
29
|
|
21
30
|
class UnidentifiedObject < ActiveRecord::Base
|
@@ -55,6 +64,11 @@ module Schema
|
|
55
64
|
t.integer :salary
|
56
65
|
end
|
57
66
|
|
67
|
+
create_table :messages, :force => true do |t|
|
68
|
+
t.integer :author_id
|
69
|
+
t.integer :recipient_id
|
70
|
+
end
|
71
|
+
|
58
72
|
create_table :unidentified_objects, :id => false, :force => true do |t|
|
59
73
|
t.integer :person_id
|
60
74
|
t.string :name
|
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: 0.8.
|
4
|
+
version: 0.8.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-08-
|
13
|
-
default_executable:
|
12
|
+
date: 2011-08-08 00:00:00.000000000Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: activerecord
|
17
|
-
requirement: &
|
16
|
+
requirement: &70170737358180 !ruby/object:Gem::Requirement
|
18
17
|
none: false
|
19
18
|
requirements:
|
20
19
|
- - ~>
|
@@ -22,10 +21,10 @@ dependencies:
|
|
22
21
|
version: '3.0'
|
23
22
|
type: :runtime
|
24
23
|
prerelease: false
|
25
|
-
version_requirements: *
|
24
|
+
version_requirements: *70170737358180
|
26
25
|
- !ruby/object:Gem::Dependency
|
27
26
|
name: activesupport
|
28
|
-
requirement: &
|
27
|
+
requirement: &70170737357560 !ruby/object:Gem::Requirement
|
29
28
|
none: false
|
30
29
|
requirements:
|
31
30
|
- - ~>
|
@@ -33,10 +32,10 @@ dependencies:
|
|
33
32
|
version: '3.0'
|
34
33
|
type: :runtime
|
35
34
|
prerelease: false
|
36
|
-
version_requirements: *
|
35
|
+
version_requirements: *70170737357560
|
37
36
|
- !ruby/object:Gem::Dependency
|
38
37
|
name: rspec
|
39
|
-
requirement: &
|
38
|
+
requirement: &70170737356940 !ruby/object:Gem::Requirement
|
40
39
|
none: false
|
41
40
|
requirements:
|
42
41
|
- - ~>
|
@@ -44,10 +43,10 @@ dependencies:
|
|
44
43
|
version: 2.6.0
|
45
44
|
type: :development
|
46
45
|
prerelease: false
|
47
|
-
version_requirements: *
|
46
|
+
version_requirements: *70170737356940
|
48
47
|
- !ruby/object:Gem::Dependency
|
49
48
|
name: machinist
|
50
|
-
requirement: &
|
49
|
+
requirement: &70170737356480 !ruby/object:Gem::Requirement
|
51
50
|
none: false
|
52
51
|
requirements:
|
53
52
|
- - ~>
|
@@ -55,10 +54,10 @@ dependencies:
|
|
55
54
|
version: 1.0.6
|
56
55
|
type: :development
|
57
56
|
prerelease: false
|
58
|
-
version_requirements: *
|
57
|
+
version_requirements: *70170737356480
|
59
58
|
- !ruby/object:Gem::Dependency
|
60
59
|
name: faker
|
61
|
-
requirement: &
|
60
|
+
requirement: &70170737356000 !ruby/object:Gem::Requirement
|
62
61
|
none: false
|
63
62
|
requirements:
|
64
63
|
- - ~>
|
@@ -66,10 +65,10 @@ dependencies:
|
|
66
65
|
version: 0.9.5
|
67
66
|
type: :development
|
68
67
|
prerelease: false
|
69
|
-
version_requirements: *
|
68
|
+
version_requirements: *70170737356000
|
70
69
|
- !ruby/object:Gem::Dependency
|
71
70
|
name: sqlite3
|
72
|
-
requirement: &
|
71
|
+
requirement: &70170737355320 !ruby/object:Gem::Requirement
|
73
72
|
none: false
|
74
73
|
requirements:
|
75
74
|
- - ~>
|
@@ -77,7 +76,7 @@ dependencies:
|
|
77
76
|
version: 1.3.3
|
78
77
|
type: :development
|
79
78
|
prerelease: false
|
80
|
-
version_requirements: *
|
79
|
+
version_requirements: *70170737355320
|
81
80
|
description: ! "\n Squeel unlocks the power of ARel in your Rails 3 application
|
82
81
|
with\n a handy block-based syntax. You can write subqueries, access named\n
|
83
82
|
\ functions provided by your RDBMS, and more, all without writing\n SQL
|
@@ -170,7 +169,6 @@ files:
|
|
170
169
|
- spec/squeel/visitors/symbol_visitor_spec.rb
|
171
170
|
- spec/support/schema.rb
|
172
171
|
- squeel.gemspec
|
173
|
-
has_rdoc: true
|
174
172
|
homepage: http://metautonomo.us/projects/squeel
|
175
173
|
licenses: []
|
176
174
|
post_install_message: ! '
|
@@ -204,7 +202,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
204
202
|
version: '0'
|
205
203
|
requirements: []
|
206
204
|
rubyforge_project: squeel
|
207
|
-
rubygems_version: 1.6
|
205
|
+
rubygems_version: 1.8.6
|
208
206
|
signing_key:
|
209
207
|
specification_version: 3
|
210
208
|
summary: ActiveRecord 3, improved.
|