squeel 1.0.14 → 1.0.15
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 +5 -0
- data/README.md +59 -7
- data/lib/squeel/adapters/active_record.rb +1 -1
- data/lib/squeel/adapters/active_record/3.0/relation_extensions.rb +6 -0
- data/lib/squeel/adapters/active_record/relation_extensions.rb +3 -3
- data/lib/squeel/nodes/key_path.rb +2 -1
- data/lib/squeel/version.rb +1 -1
- data/lib/squeel/visitors/visitor.rb +1 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/squeel/adapters/active_record/relation_extensions_spec.rb +10 -4
- data/squeel.gemspec +1 -1
- metadata +101 -108
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Squeel [](http://travis-ci.org/ernie/squeel) [](http://coderwall.com/ernie)
|
2
2
|
|
3
|
-
Squeel lets you write your
|
4
|
-
by making the ARel awesomeness that lies beneath
|
3
|
+
Squeel lets you write your Active Record queries with fewer strings, and more Ruby,
|
4
|
+
by making the ARel awesomeness that lies beneath Active Record more accessible.
|
5
5
|
|
6
6
|
Squeel lets you rewrite...
|
7
7
|
|
@@ -31,7 +31,7 @@ create a sample initializer with:
|
|
31
31
|
|
32
32
|
## The Squeel Query DSL
|
33
33
|
|
34
|
-
Squeel enhances the normal
|
34
|
+
Squeel enhances the normal Active Record query methods by enabling them to accept
|
35
35
|
blocks. Inside a block, the Squeel query DSL can be used. Note the use of curly braces
|
36
36
|
in these examples instead of parentheses. `{}` denotes a Squeel DSL query.
|
37
37
|
|
@@ -73,7 +73,7 @@ very handy.
|
|
73
73
|
### KeyPaths
|
74
74
|
|
75
75
|
A Squeel keypath is essentially a more concise and readable alternative to a
|
76
|
-
deeply nested hash. For instance, in standard
|
76
|
+
deeply nested hash. For instance, in standard Active Record, you might join several
|
77
77
|
associations like this to perform a query:
|
78
78
|
|
79
79
|
Person.joins(:articles => {:comments => :person})
|
@@ -183,13 +183,13 @@ All of the following will generate the above SQL:
|
|
183
183
|
Person.where{name == 'Joe Blow'}
|
184
184
|
|
185
185
|
Not a very exciting example since equality is handled just fine via the
|
186
|
-
first example in standard
|
186
|
+
first example in standard Active Record. But consider the following query:
|
187
187
|
|
188
188
|
SELECT "people".* FROM people
|
189
189
|
WHERE ("people"."name" LIKE 'Ernie%' AND "people"."salary" < 50000)
|
190
190
|
OR ("people"."name" LIKE 'Joe%' AND "people"."salary" > 100000)
|
191
191
|
|
192
|
-
To do this with standard
|
192
|
+
To do this with standard Active Record, we'd do something like:
|
193
193
|
|
194
194
|
Person.where(
|
195
195
|
'(name LIKE ? AND salary < ?) OR (name LIKE ? AND salary > ?)',
|
@@ -404,7 +404,59 @@ custom operator, such as the standard SQL concatenation operator, `||`:
|
|
404
404
|
|
405
405
|
As you can see, just like functions, these operations can be given aliases.
|
406
406
|
|
407
|
-
##
|
407
|
+
## Compatibility with Active Record
|
408
|
+
|
409
|
+
Most of the new functionality provided by Squeel is accessed with the new block-style `where{}`
|
410
|
+
syntax.
|
411
|
+
|
412
|
+
All your existing code that uses plain Active Record `where()` queries should continue to work the
|
413
|
+
same after adding Squeel to your project with one exception: symbols as the value side of a
|
414
|
+
condition (in normal `where()` clauses).
|
415
|
+
|
416
|
+
### Symbols as the value side of a condition (in normal `where()` clauses)
|
417
|
+
|
418
|
+
If you have any `where()` clauses that use a symbol as the value side
|
419
|
+
(right-hand side) of a condition, **you will need to change the symbol into a
|
420
|
+
string in order for it to continue to be treated as a value**.
|
421
|
+
|
422
|
+
Squeel changes the meaning of symbols in the value of a condition to refer to
|
423
|
+
the name of a **column** instead of simply treating the symbol as a **string literal**.
|
424
|
+
|
425
|
+
For example, this query:
|
426
|
+
|
427
|
+
Person.where(:first_name => :last_name)
|
428
|
+
|
429
|
+
produces this SQL query in plain Active Record:
|
430
|
+
|
431
|
+
SELECT people.* FROM people WHERE people.first_name = 'last_name'.
|
432
|
+
|
433
|
+
but produces this SQL query if you are using Squeel:
|
434
|
+
|
435
|
+
SELECT people.* FROM people WHERE people.first_name = people.last_name
|
436
|
+
|
437
|
+
Note that this new behavior applies to the plain `where()`-style expressions in addition to the new
|
438
|
+
`where{}` Squeel style.
|
439
|
+
|
440
|
+
In order for your existing `where()` clauses with symbols to continue to behave the same, you
|
441
|
+
**must** change the symbols into strings. These scopes, for example:
|
442
|
+
|
443
|
+
scope :active, where(:state => :active)
|
444
|
+
scope :in_state, lambda {|state| where(:state => state) }
|
445
|
+
|
446
|
+
should be changed to this:
|
447
|
+
|
448
|
+
scope :active, where(:state => 'active')
|
449
|
+
scope :in_state, lambda {|state| where(:state => state.to_s) }
|
450
|
+
|
451
|
+
For further information, see
|
452
|
+
[this post to the Rails list](https://groups.google.com/forum/?fromgroups=#!topic/rubyonrails-core/NQJJzZ7R7S0),
|
453
|
+
[this commit](https://github.com/lifo/docrails/commit/50c5005bafe7e43f81a141cd2c512379aec74325) to
|
454
|
+
the [Active Record guides](http://edgeguides.rubyonrails.org/active_record_querying.html#hash-conditions),
|
455
|
+
[#67](https://github.com/ernie/squeel/issues/67),
|
456
|
+
[#75](https://github.com/ernie/squeel/issues/75), and
|
457
|
+
[#171](https://github.com/ernie/squeel/issues/171).
|
458
|
+
|
459
|
+
## Compatibility with MetaWhere
|
408
460
|
|
409
461
|
While the Squeel DSL is the preferred way to access advanced query functionality, you can
|
410
462
|
still enable methods on symbols to access ARel predications in a similar manner to MetaWhere:
|
@@ -14,6 +14,12 @@ module Squeel
|
|
14
14
|
@join_dependency ||= (build_join_dependency(table, @joins_values) && @join_dependency)
|
15
15
|
end
|
16
16
|
|
17
|
+
# We don't need to call with_default_scope in AR 3.0.x. In fact, since
|
18
|
+
# there is no with_default_scope in 3.0.x, that'd be pretty dumb.
|
19
|
+
def visited
|
20
|
+
clone.visit!
|
21
|
+
end
|
22
|
+
|
17
23
|
def build_arel
|
18
24
|
arel = table
|
19
25
|
|
@@ -26,7 +26,7 @@ module Squeel
|
|
26
26
|
end
|
27
27
|
|
28
28
|
# We need to be able to support merging two relations without having
|
29
|
-
# to get our hooks too deeply into
|
29
|
+
# to get our hooks too deeply into Active Record. That proves to be
|
30
30
|
# easier said than done. I hate Relation#merge. If Squeel has a
|
31
31
|
# nemesis, Relation#merge would be it.
|
32
32
|
#
|
@@ -45,7 +45,7 @@ module Squeel
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def visited
|
48
|
-
|
48
|
+
with_default_scope.visit!
|
49
49
|
end
|
50
50
|
|
51
51
|
def visit!
|
@@ -67,7 +67,7 @@ module Squeel
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
-
# So, building a select for a count query in
|
70
|
+
# So, building a select for a count query in Active Record is
|
71
71
|
# pretty heavily dependent on select_values containing strings.
|
72
72
|
# I'd initially expected that I could just hack together a fix
|
73
73
|
# to select_for_count and everything would fall in line, but
|
@@ -170,7 +170,8 @@ module Squeel
|
|
170
170
|
path[0..-2]
|
171
171
|
end
|
172
172
|
|
173
|
-
# Implement #to_s (and alias to #to_str) to play nicely with
|
173
|
+
# Implement #to_s (and alias to #to_str) to play nicely with Active Record
|
174
|
+
# grouped calculations
|
174
175
|
def to_s
|
175
176
|
path.map(&:to_s).join('.')
|
176
177
|
end
|
data/lib/squeel/version.rb
CHANGED
@@ -352,7 +352,7 @@ module Squeel
|
|
352
352
|
op
|
353
353
|
end
|
354
354
|
|
355
|
-
# Visit an
|
355
|
+
# Visit an Active Record Relation, returning an Arel::SelectManager
|
356
356
|
# @param [ActiveRecord::Relation] o The Relation to visit
|
357
357
|
# @param parent The parent object in the context
|
358
358
|
# @return [Arel::SelectManager] The ARel select manager that represents
|
data/spec/spec_helper.rb
CHANGED
@@ -45,7 +45,7 @@ end
|
|
45
45
|
RSpec.configure do |config|
|
46
46
|
config.before(:suite) do
|
47
47
|
puts '=' * 80
|
48
|
-
puts "Running specs against
|
48
|
+
puts "Running specs against Active Record #{ActiveRecord::VERSION::STRING} and ARel #{Arel::VERSION}..."
|
49
49
|
puts '=' * 80
|
50
50
|
Models.make
|
51
51
|
end
|
@@ -430,7 +430,7 @@ module Squeel
|
|
430
430
|
counts = Person.group{name.op('||', '-diddly')}.count
|
431
431
|
counts.should eq Person.group("name || '-diddly'").count
|
432
432
|
else
|
433
|
-
pending 'Unsupported in
|
433
|
+
pending 'Unsupported in Active Record < 3.2.7'
|
434
434
|
end
|
435
435
|
end
|
436
436
|
end
|
@@ -665,12 +665,12 @@ module Squeel
|
|
665
665
|
article.person.should eq person
|
666
666
|
article.title.should eq 'Condition'
|
667
667
|
else
|
668
|
-
pending 'Unsupported on
|
668
|
+
pending 'Unsupported on Active Record < 3.1'
|
669
669
|
end
|
670
670
|
end
|
671
671
|
|
672
672
|
it 'creates new records with equality predicates from has_many :through associations' do
|
673
|
-
pending "When
|
673
|
+
pending "When Active Record supports this, we'll want to, too"
|
674
674
|
person = Person.first
|
675
675
|
comment = person.article_comments_with_first_post.new
|
676
676
|
comment.body.should eq 'first post'
|
@@ -751,7 +751,7 @@ module Squeel
|
|
751
751
|
sql.should_not match /Bill/
|
752
752
|
sql.should match /Ernie/
|
753
753
|
else
|
754
|
-
pending 'Unsupported in
|
754
|
+
pending 'Unsupported in Active Record < 3.1'
|
755
755
|
end
|
756
756
|
end
|
757
757
|
|
@@ -786,6 +786,12 @@ module Squeel
|
|
786
786
|
sql.scan(/"people"."id"/).should have(1).item
|
787
787
|
end
|
788
788
|
|
789
|
+
it "doesn't hijack the table name when merging a relation with different base and default_scope" do
|
790
|
+
relation = Article.joins(:person).merge(PersonNamedBill.scoped)
|
791
|
+
sql = relation.to_sql
|
792
|
+
sql.scan(/"people"."name" = 'Bill'/).should have(1).item
|
793
|
+
end
|
794
|
+
|
789
795
|
it 'merges scopes that contain functions' do
|
790
796
|
relation = PersonNamedBill.scoped.with_salary_equal_to(100)
|
791
797
|
sql = relation.to_sql
|
data/squeel.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.authors = ["Ernie Miller"]
|
10
10
|
s.email = ["ernie@erniemiller.org"]
|
11
11
|
s.homepage = "http://erniemiller.org/projects/squeel"
|
12
|
-
s.summary = %q{
|
12
|
+
s.summary = %q{Active Record 3, improved.}
|
13
13
|
s.description = %q{
|
14
14
|
Squeel unlocks the power of ARel in your Rails 3 application with
|
15
15
|
a handy block-based syntax. You can write subqueries, access named
|
metadata
CHANGED
@@ -1,142 +1,138 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: squeel
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.15
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 0
|
9
|
-
- 14
|
10
|
-
version: 1.0.14
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Ernie Miller
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2013-01-23 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
21
15
|
name: activerecord
|
22
|
-
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
23
17
|
none: false
|
24
|
-
requirements:
|
18
|
+
requirements:
|
25
19
|
- - ~>
|
26
|
-
- !ruby/object:Gem::Version
|
27
|
-
|
28
|
-
segments:
|
29
|
-
- 3
|
30
|
-
- 0
|
31
|
-
version: "3.0"
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.0'
|
32
22
|
type: :runtime
|
33
|
-
requirement: *id001
|
34
23
|
prerelease: false
|
35
|
-
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3.0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
36
31
|
name: activesupport
|
37
|
-
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
38
33
|
none: false
|
39
|
-
requirements:
|
34
|
+
requirements:
|
40
35
|
- - ~>
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
|
43
|
-
segments:
|
44
|
-
- 3
|
45
|
-
- 0
|
46
|
-
version: "3.0"
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '3.0'
|
47
38
|
type: :runtime
|
48
|
-
requirement: *id002
|
49
39
|
prerelease: false
|
50
|
-
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '3.0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
51
47
|
name: polyamorous
|
52
|
-
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
53
49
|
none: false
|
54
|
-
requirements:
|
50
|
+
requirements:
|
55
51
|
- - ~>
|
56
|
-
- !ruby/object:Gem::Version
|
57
|
-
hash: 11
|
58
|
-
segments:
|
59
|
-
- 0
|
60
|
-
- 5
|
61
|
-
- 0
|
52
|
+
- !ruby/object:Gem::Version
|
62
53
|
version: 0.5.0
|
63
54
|
type: :runtime
|
64
|
-
requirement: *id003
|
65
55
|
prerelease: false
|
66
|
-
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.5.0
|
62
|
+
- !ruby/object:Gem::Dependency
|
67
63
|
name: rspec
|
68
|
-
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
69
65
|
none: false
|
70
|
-
requirements:
|
66
|
+
requirements:
|
71
67
|
- - ~>
|
72
|
-
- !ruby/object:Gem::Version
|
73
|
-
hash: 23
|
74
|
-
segments:
|
75
|
-
- 2
|
76
|
-
- 6
|
77
|
-
- 0
|
68
|
+
- !ruby/object:Gem::Version
|
78
69
|
version: 2.6.0
|
79
70
|
type: :development
|
80
|
-
requirement: *id004
|
81
71
|
prerelease: false
|
82
|
-
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 2.6.0
|
78
|
+
- !ruby/object:Gem::Dependency
|
83
79
|
name: machinist
|
84
|
-
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
85
81
|
none: false
|
86
|
-
requirements:
|
82
|
+
requirements:
|
87
83
|
- - ~>
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
hash: 27
|
90
|
-
segments:
|
91
|
-
- 1
|
92
|
-
- 0
|
93
|
-
- 6
|
84
|
+
- !ruby/object:Gem::Version
|
94
85
|
version: 1.0.6
|
95
86
|
type: :development
|
96
|
-
requirement: *id005
|
97
87
|
prerelease: false
|
98
|
-
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 1.0.6
|
94
|
+
- !ruby/object:Gem::Dependency
|
99
95
|
name: faker
|
100
|
-
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
101
97
|
none: false
|
102
|
-
requirements:
|
98
|
+
requirements:
|
103
99
|
- - ~>
|
104
|
-
- !ruby/object:Gem::Version
|
105
|
-
hash: 49
|
106
|
-
segments:
|
107
|
-
- 0
|
108
|
-
- 9
|
109
|
-
- 5
|
100
|
+
- !ruby/object:Gem::Version
|
110
101
|
version: 0.9.5
|
111
102
|
type: :development
|
112
|
-
requirement: *id006
|
113
103
|
prerelease: false
|
114
|
-
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 0.9.5
|
110
|
+
- !ruby/object:Gem::Dependency
|
115
111
|
name: sqlite3
|
116
|
-
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
117
113
|
none: false
|
118
|
-
requirements:
|
114
|
+
requirements:
|
119
115
|
- - ~>
|
120
|
-
- !ruby/object:Gem::Version
|
121
|
-
hash: 29
|
122
|
-
segments:
|
123
|
-
- 1
|
124
|
-
- 3
|
125
|
-
- 3
|
116
|
+
- !ruby/object:Gem::Version
|
126
117
|
version: 1.3.3
|
127
118
|
type: :development
|
128
|
-
requirement: *id007
|
129
119
|
prerelease: false
|
130
|
-
|
131
|
-
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: 1.3.3
|
126
|
+
description: ! "\n Squeel unlocks the power of ARel in your Rails 3 application
|
127
|
+
with\n a handy block-based syntax. You can write subqueries, access named\n
|
128
|
+
\ functions provided by your RDBMS, and more, all without writing\n SQL
|
129
|
+
strings.\n "
|
130
|
+
email:
|
132
131
|
- ernie@erniemiller.org
|
133
132
|
executables: []
|
134
|
-
|
135
133
|
extensions: []
|
136
|
-
|
137
134
|
extra_rdoc_files: []
|
138
|
-
|
139
|
-
files:
|
135
|
+
files:
|
140
136
|
- .gitignore
|
141
137
|
- .travis.yml
|
142
138
|
- .yardopts
|
@@ -247,38 +243,35 @@ files:
|
|
247
243
|
- squeel.gemspec
|
248
244
|
homepage: http://erniemiller.org/projects/squeel
|
249
245
|
licenses: []
|
250
|
-
|
251
246
|
post_install_message:
|
252
247
|
rdoc_options: []
|
253
|
-
|
254
|
-
require_paths:
|
248
|
+
require_paths:
|
255
249
|
- lib
|
256
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
250
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
257
251
|
none: false
|
258
|
-
requirements:
|
259
|
-
- -
|
260
|
-
- !ruby/object:Gem::Version
|
261
|
-
|
262
|
-
segments:
|
252
|
+
requirements:
|
253
|
+
- - ! '>='
|
254
|
+
- !ruby/object:Gem::Version
|
255
|
+
version: '0'
|
256
|
+
segments:
|
263
257
|
- 0
|
264
|
-
|
265
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
258
|
+
hash: 3781393016892573538
|
259
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
266
260
|
none: false
|
267
|
-
requirements:
|
268
|
-
- -
|
269
|
-
- !ruby/object:Gem::Version
|
270
|
-
|
271
|
-
segments:
|
261
|
+
requirements:
|
262
|
+
- - ! '>='
|
263
|
+
- !ruby/object:Gem::Version
|
264
|
+
version: '0'
|
265
|
+
segments:
|
272
266
|
- 0
|
273
|
-
|
267
|
+
hash: 3781393016892573538
|
274
268
|
requirements: []
|
275
|
-
|
276
269
|
rubyforge_project: squeel
|
277
270
|
rubygems_version: 1.8.24
|
278
271
|
signing_key:
|
279
272
|
specification_version: 3
|
280
|
-
summary:
|
281
|
-
test_files:
|
273
|
+
summary: Active Record 3, improved.
|
274
|
+
test_files:
|
282
275
|
- spec/blueprints/articles.rb
|
283
276
|
- spec/blueprints/comments.rb
|
284
277
|
- spec/blueprints/notes.rb
|