squeel 1.0.14 → 1.0.15
Sign up to get free protection for your applications and to get access to all the features.
- 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 [![Build Status](https://secure.travis-ci.org/ernie/squeel.png)](http://travis-ci.org/ernie/squeel) [![endorse](http://api.coderwall.com/ernie/endorsecount.png)](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
|