baby_squeel 1.3.1 → 1.4.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +106 -9
- data/ISSUE_TEMPLATE.md +1 -1
- data/README.md +40 -8
- data/baby_squeel.gemspec +5 -6
- data/lib/baby_squeel/active_record/calculations.rb +0 -13
- data/lib/baby_squeel/active_record/query_methods.rb +49 -10
- data/lib/baby_squeel/active_record/version_helper.rb +21 -0
- data/lib/baby_squeel/association.rb +10 -10
- data/lib/baby_squeel/calculation.rb +11 -13
- data/lib/baby_squeel/errors.rb +0 -10
- data/lib/baby_squeel/join_dependency.rb +120 -30
- data/lib/baby_squeel/version.rb +1 -1
- data/lib/baby_squeel.rb +6 -1
- metadata +23 -32
- data/lib/baby_squeel/pluck.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 54dbc98299ab8f9909d8c312e9663cc615543ea6421b81f2aab6efdd2bd9fe59
|
4
|
+
data.tar.gz: 97cc39dced57e0bd6bf16c854859f47902a2d6550e71c4120643fb01d0de9529
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8f5e68cf4ac0e85d2dc8fce1741f2d64c2bd5b5ecc08c335d71ad3fae335fb3b580f5c3aa2c5f98053ec445d9a7fbc1d3ddec6c7218c99bcb9869a6767fa68c8
|
7
|
+
data.tar.gz: ca66ea54876dfb670177ccea3be1808c90b4d1affea3b7bc1cb5c515e6e8208a8b55fb9fcd06202c6411ea102a358ceb0aa7d0468f82ee7c857045fbc0c5e946
|
data/CHANGELOG.md
CHANGED
@@ -1,134 +1,224 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
-
|
3
|
+
## [1.4.4] - 2022-02-07
|
4
|
+
|
5
|
+
### Fixed
|
6
|
+
|
7
|
+
- Nested merge-joins query causes NoMethodError with ActiveRecord 6.1.4.4 (#119)
|
8
|
+
|
9
|
+
## [1.4.3] - 2022-02-04
|
10
|
+
|
11
|
+
### Fixed
|
12
|
+
|
13
|
+
- ActiveRecord::Relation#left_joins performs INNER JOIN on Active Record 6.1 (#118)
|
14
|
+
|
15
|
+
## [1.4.2] - 2022-01-24
|
16
|
+
|
17
|
+
### Fixed
|
18
|
+
|
19
|
+
- Added support for activerecord 7.0 (#116)
|
20
|
+
- Added support for activerecord 6.1 (#116)
|
21
|
+
- Added support for activerecord 6.0 (#116)
|
22
|
+
|
23
|
+
## [1.4.1] - 2021-06-17
|
24
|
+
|
25
|
+
### Fixed
|
26
|
+
|
27
|
+
- Fixed a bug related to checking the Active Record version.
|
28
|
+
|
29
|
+
## [1.4.0] - 2021-06-17
|
30
|
+
|
31
|
+
### Fixed
|
32
|
+
|
33
|
+
- Fix table alias when joining a polymorphic table twice (#108)
|
34
|
+
- Removed internal class `BabySqueel::Pluck`. You can still use `plucking`. For example, `Post.joining { author }.plucking { author.name }`
|
35
|
+
- Removed old code from Active Record < 5.2
|
36
|
+
- Removed dependency `join_dependency`
|
37
|
+
|
38
|
+
## [1.4.0.beta1] - 2021-04-21
|
39
|
+
|
40
|
+
### Fixed
|
41
|
+
|
42
|
+
- Add Support for activerecord '>= 5.2.3'
|
43
|
+
- Drop Support for Active Record versions that have reached EOL (activerecord < 5.2)
|
44
|
+
- Use polyamorous from ransack '~> 2.3'
|
4
45
|
|
5
46
|
## [1.3.1] - 2018-05-15
|
6
|
-
|
47
|
+
|
48
|
+
### Fixed
|
49
|
+
|
7
50
|
- Upgraded `join_dependency` requirement, which fixes [issue #1](https://github.com/rzane/join_dependency/issues/1).
|
8
51
|
|
9
52
|
## [1.3.0] - 2018-05-04
|
10
|
-
|
53
|
+
|
54
|
+
### Added
|
55
|
+
|
11
56
|
- The ability to use `plucking` with an array of nodes. For example, `User.plucking { [id, name] }`.
|
12
57
|
|
13
58
|
## [1.2.1] - 2018-04-25
|
14
|
-
|
59
|
+
|
60
|
+
### Fixed
|
61
|
+
|
15
62
|
- Added support for Active Record 5.2
|
16
63
|
|
17
64
|
## [1.2.0] - 2017-10-20
|
65
|
+
|
18
66
|
### Added
|
67
|
+
|
19
68
|
- `reordering`, which is just a BabySqueel version of Active Record's `reorder`.
|
20
69
|
- `on` expressions can now be given a block that will yield the current node (#77).
|
21
70
|
|
22
71
|
## [1.1.5] - 2017-05-26
|
72
|
+
|
23
73
|
### Fixed
|
74
|
+
|
24
75
|
- Returning an empty hash from a `where.has {}` block would generate invalid SQL (#69).
|
25
76
|
|
26
77
|
## [1.1.4] - 2017-04-13
|
78
|
+
|
27
79
|
### Fixed
|
80
|
+
|
28
81
|
- Nodes::Attribute#in and #not_in generate valid SQL when given ActiveRecord::NullRelations.
|
29
82
|
|
30
83
|
## [1.1.3] - 2017-03-31
|
84
|
+
|
31
85
|
### Fixed
|
86
|
+
|
32
87
|
- Nodes::Attribute#in was not returning BabySqueel node. As a result, you couldn't chain on it. This fixes #61.
|
33
88
|
|
34
89
|
## [1.1.2] - 2017-03-21
|
90
|
+
|
35
91
|
### Fixed
|
92
|
+
|
36
93
|
- Check if a reflection has a parent reflection before comparing them. This fixes #56.
|
37
94
|
|
38
95
|
### Refactored
|
96
|
+
|
39
97
|
- The logic encapsulated in `#method_missing` and `#respond_to_missing?` was difficult to follow, because it was falling back to `super`, sometimes going up the inheritance tree multiple levels. The addition of `BabySqueel::Resolver` now handles this a little more gracefully.
|
40
98
|
|
41
99
|
## [1.1.1] - 2017-02-14
|
100
|
+
|
42
101
|
### Fixed
|
102
|
+
|
43
103
|
- There is a bug in Active Record where the `AliasTracker` initializes `Arel::Table`s use the wrong `type_caster`. To address this, BabySqueel must re-initialize the `Arel::Table` with the correct `type_caster` (#54).
|
44
104
|
|
45
105
|
## [1.1.0] - 2017-02-10
|
106
|
+
|
46
107
|
> This version drops support for Active Record 4.1. If you're stil on 4.1, you should seriously consider upgrading to at least 4.2.
|
47
108
|
|
48
109
|
### Added
|
110
|
+
|
49
111
|
- DSLs for ActiveRecord::Relation::Calculations. You can now use `plucking`, `counting`, `summing`, `averaging`, `minimizing`, and `maximizing`.
|
50
112
|
|
51
113
|
## [1.0.3] - 2017-02-09
|
114
|
+
|
52
115
|
### Added
|
116
|
+
|
53
117
|
- Support for `pluck`.
|
54
118
|
- Support for `not_in`.
|
55
119
|
|
56
120
|
## [1.0.2] - 2017-02-07
|
121
|
+
|
57
122
|
### Added
|
123
|
+
|
58
124
|
- `BabySqueel::Association` now has `#==` and `#!=`. This is only supported for Rails 5+. Example: `Post.where { author: Author.last }`.
|
59
125
|
|
60
126
|
### Fixed
|
127
|
+
|
61
128
|
- Incorrect alias detection caused by not tracking the full path to a join (#37).
|
62
129
|
|
63
130
|
## [1.0.1] - 2016-11-07
|
131
|
+
|
64
132
|
### Added
|
65
|
-
|
133
|
+
|
134
|
+
- Add DSL#\_ for wrapping expressions in Arel::Node::Grouping. Thanks to [@odedniv].
|
66
135
|
|
67
136
|
### Fixed
|
137
|
+
|
68
138
|
- Use strings for attribute names like Rails does. Symbols were preventing things like `unscope` from working. Thanks to [@chewi].
|
69
139
|
- `where.has {}` will now accept `nil`.
|
70
140
|
- Arel::Nodes::Function did not previously include Arel::Math, so now you can do math operations on the result of SQL functions.
|
71
141
|
- Arel::Nodes::Binary did not previously include Arel::AliasPredication. Binary nodes can now be aliased using `as`.
|
72
142
|
|
73
143
|
## [1.0.0] - 2016-09-09
|
144
|
+
|
74
145
|
### Added
|
75
|
-
|
146
|
+
|
147
|
+
- Polyamorous. Unfortunately, this _does_ monkey-patch Active Record internals, but there just isn't any other reliable way to generate outer joins. Baby Squeel, itself, will still keep monkey patching to an absolute minimum.
|
76
148
|
- Within DSL blocks, you can use `exists` and `not_exists` with Active Record relations. For example: `Post.where.has { exists Post.where(title: 'Fun') }`.`
|
77
149
|
- Support for polymorphic associations.
|
78
150
|
|
79
151
|
### Deprecations
|
152
|
+
|
80
153
|
- Removed support for Active Record 4.0.x
|
81
154
|
|
82
155
|
### Changed
|
156
|
+
|
83
157
|
- BabySqueel::JoinDependency is no longer a class responsible for creating Arel joins. It is now a namespace for utilities used when working with the ActiveRecord::Association::JoinDependency class.
|
84
158
|
- BabySqueel::Nodes::Generic is now BabySqueel::Nodes::Node.
|
85
159
|
- Arel nodes are only extended with the behaviors they need. Previously, all Arel nodes were being extended with `Arel::AliasPredication`, `Arel::OrderPredications`, and `Arel::Math`.
|
86
160
|
|
87
161
|
### Fixed
|
162
|
+
|
88
163
|
- Fixed deprecation warnings on Active Record 5 when initializing an Arel::Table without a type caster.
|
89
164
|
- No more duplicate joins. Previously, Baby Squeel did a very poor job of ensuring that you didn't join an association twice.
|
90
|
-
- Alias detection should now
|
165
|
+
- Alias detection should now _actually_ work. The previous implementation was naive.
|
91
166
|
|
92
167
|
## [0.3.1] - 2016-08-02
|
168
|
+
|
93
169
|
### Added
|
170
|
+
|
94
171
|
- Ported backticks and #my from Squeel
|
95
172
|
|
96
173
|
### Changed
|
174
|
+
|
97
175
|
- DSL#sql now returns a node wrapped in a BabySqueel proxy.
|
98
176
|
|
99
177
|
## [0.3.0] - 2016-06-26
|
178
|
+
|
100
179
|
### Added
|
180
|
+
|
101
181
|
- Added Squeel compatibility mode that allows `select`, `order`, `joins`, `group`, `where`, and `having` to accept DSL blocks.
|
102
182
|
- Added the ability to query tables that aren't backed by Active Record models.
|
103
183
|
- Added `BabySqueel::[]`, which provides a `BabySqueel::Relation` for models, or a `BabySqueel::Table` for symbols/strings.
|
104
184
|
|
105
185
|
### Changed
|
186
|
+
|
106
187
|
- Renamed `BabySqueel::Association::AliasingError` to `BabySqueel::AssociationAliasingError`.
|
107
188
|
|
108
189
|
## [0.2.2] - 2016-03-30
|
190
|
+
|
109
191
|
### Added
|
192
|
+
|
110
193
|
- Support for `group` (`grouping`) and `having` (`when_having`).
|
111
194
|
- Support for sifters.
|
112
195
|
- Added `quoted` and `sql` helpers for quoting strings and SQL literals.
|
113
196
|
- More descriptive error messages when a column or association is not found.
|
114
197
|
|
115
198
|
### Fixed
|
199
|
+
|
116
200
|
- `Arel::Nodes::Grouping` does not include `Arel::Math`, so operations like `(id + 5) + 3` would fail unexpectedly.
|
117
201
|
- Fix missing bind values When joining through associations with default scope.
|
118
202
|
- Removed `ActiveRecord::VERSION` specific handling of the `WhereChain`.
|
119
203
|
|
120
204
|
## [0.2.1] - 2016-03-27
|
205
|
+
|
121
206
|
### Added
|
207
|
+
|
122
208
|
- Support for subqueries.
|
123
209
|
|
124
210
|
### Fixed
|
211
|
+
|
125
212
|
- Some Arel nodes did not have access to `as` expressions.
|
126
213
|
|
127
214
|
## [0.2.0] - 2016-03-25
|
215
|
+
|
128
216
|
### Added
|
217
|
+
|
129
218
|
- References to aliased joins in a `select`, `where`, or `order` expression now use the aliased table name.
|
130
219
|
|
131
220
|
### Changed
|
221
|
+
|
132
222
|
- Rely on `ActiveRecord::Relation#join_sources` for the implicit construction of join nodes, rather than using the `ActiveRecord::Associations::JoinDependency` directly.
|
133
223
|
|
134
224
|
### Fixed
|
@@ -136,10 +226,18 @@ Nothing to see here.
|
|
136
226
|
- Associations referencing the same table weren't being aliased.
|
137
227
|
|
138
228
|
## [0.1.0] - 2016-03-16
|
229
|
+
|
139
230
|
### Added
|
231
|
+
|
140
232
|
- Initial support for selects, orders, wheres, and joins.
|
141
233
|
|
142
|
-
[
|
234
|
+
[unreleased]: https://github.com/rzane/baby_squeel/compare/v1.4.4...HEAD
|
235
|
+
[1.4.4]: https://github.com/rzane/baby_squeel/compare/v1.4.3...v1.4.4
|
236
|
+
[1.4.3]: https://github.com/rzane/baby_squeel/compare/v1.4.2...v1.4.3
|
237
|
+
[1.4.2]: https://github.com/rzane/baby_squeel/compare/v1.4.1...v1.4.2
|
238
|
+
[1.4.1]: https://github.com/rzane/baby_squeel/compare/v1.4.0...v1.4.1
|
239
|
+
[1.4.0]: https://github.com/rzane/baby_squeel/compare/v1.4.0.beta1...v1.4.0
|
240
|
+
[1.4.0.beta1]: https://github.com/rzane/baby_squeel/compare/v1.3.1...v1.4.0.beta1
|
143
241
|
[1.3.1]: https://github.com/rzane/baby_squeel/compare/v1.3.0...v1.3.1
|
144
242
|
[1.3.0]: https://github.com/rzane/baby_squeel/compare/v1.2.1...v1.3.0
|
145
243
|
[1.2.1]: https://github.com/rzane/baby_squeel/compare/v1.2.0...v1.2.1
|
@@ -159,6 +257,5 @@ Nothing to see here.
|
|
159
257
|
[0.2.2]: https://github.com/rzane/baby_squeel/compare/v0.2.1...v0.2.2
|
160
258
|
[0.2.1]: https://github.com/rzane/baby_squeel/compare/v0.2.0...v0.2.1
|
161
259
|
[0.2.0]: https://github.com/rzane/baby_squeel/compare/v0.1.0...v0.2.0
|
162
|
-
|
163
260
|
[@chewi]: https://github.com/chewi
|
164
261
|
[@odedniv]: https://github.com/odedniv
|
data/ISSUE_TEMPLATE.md
CHANGED
@@ -11,7 +11,7 @@ require 'minitest/autorun'
|
|
11
11
|
|
12
12
|
gemfile true do
|
13
13
|
source 'https://rubygems.org'
|
14
|
-
gem 'activerecord', '~> 5.
|
14
|
+
gem 'activerecord', '~> 5.2.0' # which Active Record version?
|
15
15
|
gem 'sqlite3'
|
16
16
|
gem 'baby_squeel', github: 'rzane/baby_squeel'
|
17
17
|
end
|
data/README.md
CHANGED
@@ -1,10 +1,7 @@
|
|
1
|
-
# BabySqueel
|
1
|
+
# BabySqueel 🐷
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
[![Coverage Status](https://coveralls.io/repos/github/rzane/baby_squeel/badge.svg?branch=master)](https://coveralls.io/github/rzane/baby_squeel?branch=master)
|
6
|
-
|
7
|
-
<img align="right" src="http://static.thefrisky.com/uploads/2010/07/01/pig_in_boots_070110_m.jpg" alt="biddy piggy">
|
3
|
+
![Build](https://github.com/rzane/baby_squeel/workflows/Build/badge.svg)
|
4
|
+
![Version](https://img.shields.io/gem/v/baby_squeel)
|
8
5
|
|
9
6
|
Have you ever used the [Squeel](https://github.com/activerecord-hackery/squeel) gem? It's a really nice way to build complex queries. However, Squeel monkeypatches Active Record internals, because it was aimed at enhancing the existing API with the aim of inclusion into Rails. However, that inclusion never happened, and it left Squeel susceptible to breakage from arbitrary changes in Active Record, eventually burning out the maintainer.
|
10
7
|
|
@@ -219,6 +216,21 @@ Post.joins(:author).where.has {
|
|
219
216
|
# )
|
220
217
|
```
|
221
218
|
|
219
|
+
##### Exists
|
220
|
+
|
221
|
+
```ruby
|
222
|
+
Post.where.has {
|
223
|
+
exists Post.where.has { author_id == 1 }
|
224
|
+
}
|
225
|
+
# SELECT "posts".* FROM "posts"
|
226
|
+
# WHERE (
|
227
|
+
# EXISTS(
|
228
|
+
# SELECT "posts".* FROM "posts"
|
229
|
+
# WHERE "posts"."author_id" = 1
|
230
|
+
# )
|
231
|
+
# )
|
232
|
+
```
|
233
|
+
|
222
234
|
##### Custom SQL Operators
|
223
235
|
|
224
236
|
```ruby
|
@@ -240,6 +252,26 @@ Post.joining {
|
|
240
252
|
}
|
241
253
|
```
|
242
254
|
|
255
|
+
##### Polymorphism
|
256
|
+
|
257
|
+
Given this polymorphism:
|
258
|
+
|
259
|
+
```ruby
|
260
|
+
# app/models/picture.rb
|
261
|
+
belongs_to :imageable, polymorphic: true
|
262
|
+
|
263
|
+
# app/models/post.rb
|
264
|
+
has_many :pictures, as: :imageable
|
265
|
+
```
|
266
|
+
|
267
|
+
The query might look like this:
|
268
|
+
|
269
|
+
```ruby
|
270
|
+
Picture.
|
271
|
+
joining { imageable.of(Post) }.
|
272
|
+
selecting { imageable.of(Post).id }
|
273
|
+
```
|
274
|
+
|
243
275
|
##### Helpers
|
244
276
|
|
245
277
|
```ruby
|
@@ -283,7 +315,7 @@ Post.joins(:author).where.has {
|
|
283
315
|
The following methods give you access to BabySqueel's DSL:
|
284
316
|
|
285
317
|
| BabySqueel | Active Record Equivalent |
|
286
|
-
|
318
|
+
| ------------- | ------------------------ |
|
287
319
|
| `selecting` | `select` |
|
288
320
|
| `ordering` | `order` |
|
289
321
|
| `joining` | `joins` |
|
@@ -297,7 +329,7 @@ Check out the [migration guide](https://github.com/rzane/baby_squeel/wiki/Migrat
|
|
297
329
|
|
298
330
|
## Development
|
299
331
|
|
300
|
-
1. Pick an Active Record version to develop against, then export it: `export AR=
|
332
|
+
1. Pick an Active Record version to develop against, then export it: `export AR=6.1.4`.
|
301
333
|
2. Run `bin/setup` to install dependencies.
|
302
334
|
3. Run `rake` to run the specs.
|
303
335
|
|
data/baby_squeel.gemspec
CHANGED
@@ -19,12 +19,11 @@ Gem::Specification.new do |spec|
|
|
19
19
|
|
20
20
|
spec.files = Dir.glob('{lib/**/*,*.{md,txt,gemspec}}')
|
21
21
|
|
22
|
-
spec.add_dependency 'activerecord', '>=
|
23
|
-
spec.add_dependency '
|
24
|
-
spec.add_dependency 'join_dependency', '~> 0.1.2'
|
22
|
+
spec.add_dependency 'activerecord', '>= 5.2', '< 7.1'
|
23
|
+
spec.add_dependency 'ransack', '~> 2.3'
|
25
24
|
|
26
|
-
spec.add_development_dependency 'bundler', '~>
|
27
|
-
spec.add_development_dependency 'rake', '~>
|
28
|
-
spec.add_development_dependency 'rspec', '~> 3.
|
25
|
+
spec.add_development_dependency 'bundler', '~> 2'
|
26
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
27
|
+
spec.add_development_dependency 'rspec', '~> 3.10'
|
29
28
|
spec.add_development_dependency 'sqlite3'
|
30
29
|
end
|
@@ -1,12 +1,10 @@
|
|
1
1
|
require 'baby_squeel/calculation'
|
2
|
-
require 'baby_squeel/pluck'
|
3
2
|
|
4
3
|
module BabySqueel
|
5
4
|
module ActiveRecord
|
6
5
|
module Calculations
|
7
6
|
def plucking(&block)
|
8
7
|
nodes = Array.wrap(DSL.evaluate(self, &block))
|
9
|
-
nodes = nodes.map { |node| Pluck.decorate(node) }
|
10
8
|
pluck(*nodes)
|
11
9
|
end
|
12
10
|
|
@@ -40,17 +38,6 @@ module BabySqueel
|
|
40
38
|
super
|
41
39
|
end
|
42
40
|
end
|
43
|
-
|
44
|
-
if ::ActiveRecord::VERSION::MAJOR < 5
|
45
|
-
# @override
|
46
|
-
def type_for(field)
|
47
|
-
if field.kind_of? Calculation
|
48
|
-
field
|
49
|
-
else
|
50
|
-
super
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
41
|
end
|
55
42
|
end
|
56
43
|
end
|
@@ -1,9 +1,26 @@
|
|
1
1
|
require 'baby_squeel/dsl'
|
2
2
|
require 'baby_squeel/join_dependency'
|
3
|
+
require 'baby_squeel/active_record/version_helper'
|
3
4
|
|
4
5
|
module BabySqueel
|
5
6
|
module ActiveRecord
|
6
7
|
module QueryMethods
|
8
|
+
# This class allows BabySqueel to slip custom
|
9
|
+
# joins_values into Active Record's JoinDependency
|
10
|
+
module Injector6_1
|
11
|
+
def each(&block)
|
12
|
+
super do |join|
|
13
|
+
if join.is_a?(BabySqueel::Join)
|
14
|
+
result = block.binding.local_variables.include?(:result) && block.binding.local_variable_get(:result)
|
15
|
+
result << join if result
|
16
|
+
join
|
17
|
+
else
|
18
|
+
block.call(join)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
7
24
|
# Constructs Arel for ActiveRecord::QueryMethods#joins using the DSL.
|
8
25
|
def joining(&block)
|
9
26
|
joins DSL.evaluate(self, &block)
|
@@ -34,19 +51,41 @@ module BabySqueel
|
|
34
51
|
having DSL.evaluate(self, &block)
|
35
52
|
end
|
36
53
|
|
37
|
-
|
54
|
+
if BabySqueel::ActiveRecord::VersionHelper.at_least_6_1?
|
55
|
+
def construct_join_dependency(associations, join_type)
|
56
|
+
result = super(associations, join_type)
|
57
|
+
if associations.any? { |assoc| assoc.is_a?(BabySqueel::Join) }
|
58
|
+
result.extend(BabySqueel::JoinDependency::Injector6_1)
|
59
|
+
end
|
60
|
+
result
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
# https://github.com/rails/rails/commit/c0c53ee9d28134757cf1418521cb97c4a135f140
|
66
|
+
def select_association_list(*args)
|
67
|
+
args[0].extend(BabySqueel::ActiveRecord::QueryMethods::Injector6_1)
|
68
|
+
super *args
|
69
|
+
end
|
70
|
+
elsif BabySqueel::ActiveRecord::VersionHelper.at_least_6_0?
|
71
|
+
private
|
38
72
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
super manager, BabySqueel::JoinDependency::Injector.new(joins), aliases
|
73
|
+
# Active Record will call `each` on the `joins`. The
|
74
|
+
# Injector has a custom `each` method that handles
|
75
|
+
# BabySqueel::Join nodes.
|
76
|
+
def build_joins(*args)
|
77
|
+
args[1] = BabySqueel::JoinDependency::Injector6_0.new(args.second)
|
78
|
+
super(*args)
|
46
79
|
end
|
47
80
|
else
|
48
|
-
|
49
|
-
|
81
|
+
private
|
82
|
+
|
83
|
+
# Active Record will call `group_by` on the `joins`. The
|
84
|
+
# Injector has a custom `group_by` method that handles
|
85
|
+
# BabySqueel::Join nodes.
|
86
|
+
def build_joins(*args)
|
87
|
+
args[1] = BabySqueel::JoinDependency::Injector5_2.new(args.second)
|
88
|
+
super(*args)
|
50
89
|
end
|
51
90
|
end
|
52
91
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'baby_squeel/dsl'
|
2
|
+
|
3
|
+
module BabySqueel
|
4
|
+
module ActiveRecord
|
5
|
+
class VersionHelper
|
6
|
+
def self.at_least_6_1?
|
7
|
+
::ActiveRecord::VERSION::MAJOR > 6 ||
|
8
|
+
::ActiveRecord::VERSION::MAJOR == 6 && ::ActiveRecord::VERSION::MINOR >= 1
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.at_least_6_0?
|
12
|
+
::ActiveRecord::VERSION::MAJOR >= 6
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.at_least_5_2_3?
|
16
|
+
at_least_6_0? ||
|
17
|
+
::ActiveRecord::VERSION::MAJOR >= 5 && ::ActiveRecord::VERSION::MINOR >= 2 && ::ActiveRecord::VERSION::TINY >= 3
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'baby_squeel/relation'
|
2
|
+
require 'baby_squeel/active_record/version_helper'
|
2
3
|
|
3
4
|
module BabySqueel
|
4
5
|
class Association < Relation
|
@@ -96,19 +97,18 @@ module BabySqueel
|
|
96
97
|
|
97
98
|
private
|
98
99
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
100
|
+
def build_where_clause(other)
|
101
|
+
if valid_where_clause?(other)
|
102
|
+
relation = @parent._scope.all
|
103
|
+
|
104
|
+
if BabySqueel::ActiveRecord::VersionHelper.at_least_6_1?
|
105
|
+
relation.send(:build_where_clause, { _reflection.name => other }, [])
|
106
|
+
else
|
103
107
|
factory = relation.send(:where_clause_factory)
|
104
108
|
factory.build({ _reflection.name => other }, [])
|
105
|
-
else
|
106
|
-
raise AssociationComparisonError.new(_reflection.name, other)
|
107
109
|
end
|
108
|
-
|
109
|
-
|
110
|
-
def build_where_clause(_)
|
111
|
-
raise AssociationComparisonNotSupportedError.new(_reflection.name)
|
110
|
+
else
|
111
|
+
raise AssociationComparisonError.new(_reflection.name, other)
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
@@ -6,12 +6,6 @@ module BabySqueel
|
|
6
6
|
@node = node
|
7
7
|
end
|
8
8
|
|
9
|
-
# This is only used in 4.2. We're just pretending to be
|
10
|
-
# a database column to fake the casting here.
|
11
|
-
def type_cast_from_database(value)
|
12
|
-
value
|
13
|
-
end
|
14
|
-
|
15
9
|
# In Active Record 5, we don't *need* this class to make
|
16
10
|
# calculations work. They happily accept arel. However,
|
17
11
|
# when grouping with a calculation, there's a really,
|
@@ -21,15 +15,19 @@ module BabySqueel
|
|
21
15
|
# caching because the alias would have a unique name every
|
22
16
|
# time.
|
23
17
|
def to_s
|
24
|
-
|
25
|
-
|
26
|
-
child.
|
27
|
-
|
28
|
-
child.name
|
18
|
+
if node.respond_to?(:map)
|
19
|
+
names = node.map do |child|
|
20
|
+
if child.kind_of?(String) || child.kind_of?(Symbol)
|
21
|
+
child.to_s
|
22
|
+
elsif child.respond_to?(:name)
|
23
|
+
child.name.to_s
|
24
|
+
end
|
29
25
|
end
|
26
|
+
names.compact.uniq.join('_')
|
27
|
+
else
|
28
|
+
# fix for https://github.com/rails/rails/commit/fc38ff6e4417295c870f419f7c164ab5a7dbc4a5
|
29
|
+
node.to_sql.split('"').map { |v| v.tr('^A-Za-z0-9_', '').presence }.compact.uniq.join('_')
|
30
30
|
end
|
31
|
-
|
32
|
-
names.compact.uniq.join('_')
|
33
31
|
end
|
34
32
|
end
|
35
33
|
end
|
data/lib/baby_squeel/errors.rb
CHANGED
@@ -62,14 +62,4 @@ module BabySqueel
|
|
62
62
|
super "You can't compare association '#{name}' to #{other}."
|
63
63
|
end
|
64
64
|
end
|
65
|
-
|
66
|
-
class AssociationComparisonNotSupportedError < StandardError # :nodoc:
|
67
|
-
MESSAGE =
|
68
|
-
"Querying association '%{name}' with '==' and '!=' " \
|
69
|
-
"is only supported for ActiveRecord >=5."
|
70
|
-
|
71
|
-
def initialize(name)
|
72
|
-
super format(MESSAGE, name: name)
|
73
|
-
end
|
74
|
-
end
|
75
65
|
end
|
@@ -1,10 +1,10 @@
|
|
1
|
-
require '
|
1
|
+
require 'baby_squeel/active_record/version_helper'
|
2
2
|
|
3
3
|
module BabySqueel
|
4
4
|
module JoinDependency
|
5
5
|
# This class allows BabySqueel to slip custom
|
6
6
|
# joins_values into Active Record's JoinDependency
|
7
|
-
class
|
7
|
+
class Injector5_2 < Array # :nodoc:
|
8
8
|
# Active Record will call group_by on this object
|
9
9
|
# in ActiveRecord::QueryMethods#build_joins. This
|
10
10
|
# allows BabySqueel::Joins to be treated
|
@@ -22,56 +22,146 @@ module BabySqueel
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
# This class allows BabySqueel to slip custom
|
26
|
+
# joins_values into Active Record's JoinDependency
|
27
|
+
class Injector6_0 < Array # :nodoc:
|
28
|
+
# https://github.com/rails/rails/pull/36805/files
|
29
|
+
# This commit changed group_by to each
|
30
|
+
def each(&block)
|
31
|
+
super do |join|
|
32
|
+
if block.binding.local_variables.include?(:buckets)
|
33
|
+
buckets = block.binding.local_variable_get(:buckets)
|
34
|
+
|
35
|
+
case join
|
36
|
+
when BabySqueel::Join
|
37
|
+
buckets[:association_join] << join
|
38
|
+
else
|
39
|
+
block.call(join)
|
40
|
+
end
|
41
|
+
else
|
42
|
+
block.call(join)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# This is a 'fix' for the left outer joins
|
49
|
+
# rails way would be to call left_outer_joins so the join_type gets set to Arel::Nodes::OuterJoin
|
50
|
+
# Maybe this could be fixed in joining but I do not know how.
|
51
|
+
module Injector6_1 # :nodoc:
|
52
|
+
def make_constraints(parent, child, join_type) # :nodoc:
|
53
|
+
join_type = child.join_type if child.join_type == Arel::Nodes::OuterJoin
|
54
|
+
super(parent, child, join_type)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
25
58
|
class Builder # :nodoc:
|
26
59
|
attr_reader :join_dependency
|
27
60
|
|
28
61
|
def initialize(relation)
|
29
|
-
@join_dependency =
|
30
|
-
:association_join if join.kind_of? BabySqueel::Join
|
31
|
-
end
|
62
|
+
@join_dependency = build(relation, collect_joins(relation))
|
32
63
|
end
|
33
64
|
|
34
65
|
# Find the alias of a BabySqueel::Association, by passing
|
35
66
|
# a list (in order of chaining) of associations and finding
|
36
67
|
# the respective JoinAssociation at each level.
|
37
68
|
def find_alias(associations)
|
38
|
-
|
39
|
-
|
69
|
+
if BabySqueel::ActiveRecord::VersionHelper.at_least_6_1?
|
70
|
+
# construct_tables! got removed by rails
|
71
|
+
# https://github.com/rails/rails/commit/590b045ee2c0906ff162e6658a184afb201865d7
|
72
|
+
#
|
73
|
+
# construct_tables_for_association! is a method from the polyamorous (ransack) gem
|
74
|
+
join_root = join_dependency.send(:join_root)
|
75
|
+
join_root.each_children do |parent, child|
|
76
|
+
join_dependency.construct_tables_for_association!(parent, child)
|
77
|
+
end
|
78
|
+
elsif BabySqueel::ActiveRecord::VersionHelper.at_least_5_2_3?
|
79
|
+
# If we tell join_dependency to construct its tables, Active Record
|
80
|
+
# handles building the correct aliases and attaching them to its
|
81
|
+
# JoinDepenencies.
|
82
|
+
join_dependency.send(:construct_tables!, join_dependency.send(:join_root))
|
83
|
+
end
|
84
|
+
|
85
|
+
join_association = find_join_association(associations)
|
86
|
+
join_association.table
|
40
87
|
end
|
41
88
|
|
42
89
|
private
|
43
90
|
|
91
|
+
Associations = ::ActiveRecord::Associations
|
92
|
+
|
44
93
|
def find_join_association(associations)
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
94
|
+
current = join_dependency.send(:join_root)
|
95
|
+
|
96
|
+
associations.each do |association|
|
97
|
+
name = association._reflection.name
|
98
|
+
current = current.children.find { |c| c.reflection.name == name && klass_equal?(association, c) }
|
99
|
+
break if current.nil?
|
52
100
|
end
|
101
|
+
|
102
|
+
current
|
53
103
|
end
|
54
104
|
|
55
|
-
#
|
56
|
-
|
57
|
-
|
105
|
+
# If association is not polymorphic return true.
|
106
|
+
# If association is polymorphic compare the association polymorphic class with the join association base_klass
|
107
|
+
def klass_equal?(assoc, join_association)
|
108
|
+
return true unless assoc._reflection.polymorphic?
|
109
|
+
|
110
|
+
assoc._polymorphic_klass == join_association.base_klass
|
58
111
|
end
|
59
112
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
113
|
+
def collect_joins(relation)
|
114
|
+
joins = []
|
115
|
+
joins += relation.joins_values
|
116
|
+
joins += relation.left_outer_joins_values
|
117
|
+
|
118
|
+
buckets = joins.group_by do |join|
|
119
|
+
case join
|
120
|
+
when String
|
121
|
+
:string_join
|
122
|
+
when Hash, Symbol, Array
|
123
|
+
:association_join
|
124
|
+
when Associations::JoinDependency
|
125
|
+
:stashed_join
|
126
|
+
when Arel::Nodes::Join
|
127
|
+
:join_node
|
128
|
+
when BabySqueel::Join
|
129
|
+
:association_join
|
130
|
+
else
|
131
|
+
raise("unknown class: %s" % join.class.name)
|
132
|
+
end
|
133
|
+
end
|
65
134
|
end
|
66
135
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
136
|
+
def build(relation, buckets)
|
137
|
+
buckets.default = []
|
138
|
+
association_joins = buckets[:association_join]
|
139
|
+
stashed_association_joins = buckets[:stashed_join]
|
140
|
+
join_nodes = buckets[:join_node].uniq
|
141
|
+
string_joins = buckets[:string_join].map(&:strip).uniq
|
142
|
+
|
143
|
+
joins = string_joins.map do |join|
|
144
|
+
relation.table.create_string_join(Arel.sql(join)) unless join.blank?
|
145
|
+
end.compact
|
146
|
+
|
147
|
+
join_list = join_nodes + joins
|
148
|
+
|
149
|
+
alias_tracker = Associations::AliasTracker.create(relation.klass.connection, relation.table.name, join_list)
|
150
|
+
if BabySqueel::ActiveRecord::VersionHelper.at_least_6_0?
|
151
|
+
join_dependency = Associations::JoinDependency.new(relation.klass, relation.table, association_joins, Arel::Nodes::InnerJoin)
|
152
|
+
join_dependency.instance_variable_set(:@alias_tracker, alias_tracker)
|
153
|
+
elsif BabySqueel::ActiveRecord::VersionHelper.at_least_5_2_3?
|
154
|
+
join_dependency = Associations::JoinDependency.new(relation.klass, relation.table, association_joins)
|
155
|
+
join_dependency.instance_variable_set(:@alias_tracker, alias_tracker)
|
156
|
+
else
|
157
|
+
# Rails 5.2.0 - 5.2.2
|
158
|
+
join_dependency = Associations::JoinDependency.new(relation.klass, relation.table, association_joins, alias_tracker)
|
159
|
+
end
|
160
|
+
join_nodes.each do |join|
|
161
|
+
join_dependency.send(:alias_tracker).aliases[join.left.name.downcase] = 1
|
162
|
+
end
|
163
|
+
|
164
|
+
join_dependency
|
75
165
|
end
|
76
166
|
end
|
77
167
|
end
|
data/lib/baby_squeel/version.rb
CHANGED
data/lib/baby_squeel.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
require 'active_record'
|
2
2
|
require 'active_record/relation'
|
3
|
-
|
3
|
+
begin
|
4
|
+
require 'polyamorous'
|
5
|
+
rescue LoadError
|
6
|
+
# Trying loading from 'ransack' as of commit c9cc20de9 (post v2.3.2)
|
7
|
+
require 'polyamorous/polyamorous'
|
8
|
+
end
|
4
9
|
require 'baby_squeel/version'
|
5
10
|
require 'baby_squeel/errors'
|
6
11
|
require 'baby_squeel/active_record/base'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: baby_squeel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ray Zane
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-02-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -16,84 +16,76 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: '5.2'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '7.1'
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
27
|
- - ">="
|
25
28
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
27
|
-
-
|
28
|
-
name: polyamorous
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '1.3'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
29
|
+
version: '5.2'
|
30
|
+
- - "<"
|
39
31
|
- !ruby/object:Gem::Version
|
40
|
-
version: '1
|
32
|
+
version: '7.1'
|
41
33
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
34
|
+
name: ransack
|
43
35
|
requirement: !ruby/object:Gem::Requirement
|
44
36
|
requirements:
|
45
37
|
- - "~>"
|
46
38
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
39
|
+
version: '2.3'
|
48
40
|
type: :runtime
|
49
41
|
prerelease: false
|
50
42
|
version_requirements: !ruby/object:Gem::Requirement
|
51
43
|
requirements:
|
52
44
|
- - "~>"
|
53
45
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
46
|
+
version: '2.3'
|
55
47
|
- !ruby/object:Gem::Dependency
|
56
48
|
name: bundler
|
57
49
|
requirement: !ruby/object:Gem::Requirement
|
58
50
|
requirements:
|
59
51
|
- - "~>"
|
60
52
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
53
|
+
version: '2'
|
62
54
|
type: :development
|
63
55
|
prerelease: false
|
64
56
|
version_requirements: !ruby/object:Gem::Requirement
|
65
57
|
requirements:
|
66
58
|
- - "~>"
|
67
59
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
60
|
+
version: '2'
|
69
61
|
- !ruby/object:Gem::Dependency
|
70
62
|
name: rake
|
71
63
|
requirement: !ruby/object:Gem::Requirement
|
72
64
|
requirements:
|
73
65
|
- - "~>"
|
74
66
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
67
|
+
version: '13.0'
|
76
68
|
type: :development
|
77
69
|
prerelease: false
|
78
70
|
version_requirements: !ruby/object:Gem::Requirement
|
79
71
|
requirements:
|
80
72
|
- - "~>"
|
81
73
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
74
|
+
version: '13.0'
|
83
75
|
- !ruby/object:Gem::Dependency
|
84
76
|
name: rspec
|
85
77
|
requirement: !ruby/object:Gem::Requirement
|
86
78
|
requirements:
|
87
79
|
- - "~>"
|
88
80
|
- !ruby/object:Gem::Version
|
89
|
-
version: 3.
|
81
|
+
version: '3.10'
|
90
82
|
type: :development
|
91
83
|
prerelease: false
|
92
84
|
version_requirements: !ruby/object:Gem::Requirement
|
93
85
|
requirements:
|
94
86
|
- - "~>"
|
95
87
|
- !ruby/object:Gem::Version
|
96
|
-
version: 3.
|
88
|
+
version: '3.10'
|
97
89
|
- !ruby/object:Gem::Dependency
|
98
90
|
name: sqlite3
|
99
91
|
requirement: !ruby/object:Gem::Requirement
|
@@ -124,6 +116,7 @@ files:
|
|
124
116
|
- lib/baby_squeel/active_record/base.rb
|
125
117
|
- lib/baby_squeel/active_record/calculations.rb
|
126
118
|
- lib/baby_squeel/active_record/query_methods.rb
|
119
|
+
- lib/baby_squeel/active_record/version_helper.rb
|
127
120
|
- lib/baby_squeel/active_record/where_chain.rb
|
128
121
|
- lib/baby_squeel/association.rb
|
129
122
|
- lib/baby_squeel/calculation.rb
|
@@ -140,7 +133,6 @@ files:
|
|
140
133
|
- lib/baby_squeel/nodes/node.rb
|
141
134
|
- lib/baby_squeel/nodes/proxy.rb
|
142
135
|
- lib/baby_squeel/operators.rb
|
143
|
-
- lib/baby_squeel/pluck.rb
|
144
136
|
- lib/baby_squeel/relation.rb
|
145
137
|
- lib/baby_squeel/resolver.rb
|
146
138
|
- lib/baby_squeel/table.rb
|
@@ -149,7 +141,7 @@ homepage: https://github.com/rzane/baby_squeel
|
|
149
141
|
licenses:
|
150
142
|
- MIT
|
151
143
|
metadata: {}
|
152
|
-
post_install_message:
|
144
|
+
post_install_message:
|
153
145
|
rdoc_options: []
|
154
146
|
require_paths:
|
155
147
|
- lib
|
@@ -164,9 +156,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
164
156
|
- !ruby/object:Gem::Version
|
165
157
|
version: '0'
|
166
158
|
requirements: []
|
167
|
-
|
168
|
-
|
169
|
-
signing_key:
|
159
|
+
rubygems_version: 3.3.3
|
160
|
+
signing_key:
|
170
161
|
specification_version: 4
|
171
162
|
summary: An expressive query DSL for Active Record 4 and 5.
|
172
163
|
test_files: []
|
data/lib/baby_squeel/pluck.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
module BabySqueel
|
2
|
-
class Pluck # :nodoc:
|
3
|
-
# In Active Record 4.2, #pluck chokes when you give it
|
4
|
-
# Arel. It calls #to_s on whatever you pass in. So the
|
5
|
-
# hacky solution is to wrap the node in a class that
|
6
|
-
# returns the node when you call #to_s. Then, it works!
|
7
|
-
#
|
8
|
-
# In Active Record 5, #pluck accepts Arel, so we won't
|
9
|
-
# bother to use this there.
|
10
|
-
|
11
|
-
if ::ActiveRecord::VERSION::MAJOR >= 5
|
12
|
-
def self.decorate(node); node; end
|
13
|
-
else
|
14
|
-
def self.decorate(node); new(node); end
|
15
|
-
end
|
16
|
-
|
17
|
-
def initialize(node)
|
18
|
-
@node = node
|
19
|
-
end
|
20
|
-
|
21
|
-
def to_s
|
22
|
-
@node
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|