baby_squeel 1.4.0.beta1 → 1.4.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2df3535278f1724c6db1656ab9c5bbe0e9097e80ee6f2c1fdaeb3491bc838ae9
4
- data.tar.gz: bddd464023f9f53f0ff32cc1fbaa88928f5736b3e6541418b8c36f26b01b8d34
3
+ metadata.gz: 54dbc98299ab8f9909d8c312e9663cc615543ea6421b81f2aab6efdd2bd9fe59
4
+ data.tar.gz: 97cc39dced57e0bd6bf16c854859f47902a2d6550e71c4120643fb01d0de9529
5
5
  SHA512:
6
- metadata.gz: 44f8ecb2269017a1e141f0f90d5c9a7eee7d5b877500897aba0a60646f38de0cdae4b992f505d022740c03e73d6293990d9f509d5b3188b5be8051819e168069
7
- data.tar.gz: a63f7b474504ef598508879d8ad702396f194c663cc46ececdb9c8dd31aabb10752323332bc26b3cec5cfb2df93e5328e11d2ce1983efe23793c618ccce9294d
6
+ metadata.gz: 8f5e68cf4ac0e85d2dc8fce1741f2d64c2bd5b5ecc08c335d71ad3fae335fb3b580f5c3aa2c5f98053ec445d9a7fbc1d3ddec6c7218c99bcb9869a6767fa68c8
7
+ data.tar.gz: ca66ea54876dfb670177ccea3be1808c90b4d1affea3b7bc1cb5c515e6e8208a8b55fb9fcd06202c6411ea102a358ceb0aa7d0468f82ee7c857045fbc0c5e946
data/CHANGELOG.md CHANGED
@@ -1,134 +1,224 @@
1
1
  ## [Unreleased]
2
2
 
3
- Nothing to see here.
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
- ## Fixed
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
- ## Added
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
- ## Fixed
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
- - Add DSL#_ for wrapping expressions in Arel::Node::Grouping. Thanks to [@odedniv].
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
- - 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.
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 *actually* work. The previous implementation was naive.
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
- [Unreleased]: https://github.com/rzane/baby_squeel/compare/v1.3.1...HEAD
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.0.0' # which Active Record version?
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
@@ -329,7 +329,7 @@ Check out the [migration guide](https://github.com/rzane/baby_squeel/wiki/Migrat
329
329
 
330
330
  ## Development
331
331
 
332
- 1. Pick an Active Record version to develop against, then export it: `export AR=4.2.6`.
332
+ 1. Pick an Active Record version to develop against, then export it: `export AR=6.1.4`.
333
333
  2. Run `bin/setup` to install dependencies.
334
334
  3. Run `rake` to run the specs.
335
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', '~> 5.2'
22
+ spec.add_dependency 'activerecord', '>= 5.2', '< 7.1'
23
23
  spec.add_dependency 'ransack', '~> 2.3'
24
- spec.add_dependency 'join_dependency', '~> 0.1.4'
25
24
 
26
25
  spec.add_development_dependency 'bundler', '~> 2'
27
26
  spec.add_development_dependency 'rake', '~> 13.0'
28
27
  spec.add_development_dependency 'rspec', '~> 3.10'
29
- spec.add_development_dependency 'sqlite3', '~> 1.3.6'
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
- private
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
- # This is a monkey patch, and I'm not happy about it.
40
- # Active Record will call `group_by` on the `joins`. The
41
- # Injector has a custom `group_by` method that handles
42
- # BabySqueel::Join nodes.
43
- if ::ActiveRecord::VERSION::MAJOR >= 5 && ::ActiveRecord::VERSION::MINOR >= 2
44
- def build_joins(manager, joins, aliases)
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
- def build_joins(manager, joins)
49
- super manager, BabySqueel::JoinDependency::Injector.new(joins)
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
- if ActiveRecord::VERSION::MAJOR >= 5
100
- def build_where_clause(other)
101
- if valid_where_clause?(other)
102
- relation = @parent._scope.all
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
- end
109
- else
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
- names = node.map do |child|
25
- if child.kind_of?(String) || child.kind_of?(Symbol)
26
- child.to_s
27
- elsif child.respond_to?(:name)
28
- child.name.to_s
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
@@ -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 'join_dependency'
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 Injector < Array # :nodoc:
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,23 +22,63 @@ 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 = ::JoinDependency.from_relation(relation) do |join|
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
- # If we tell join_dependency to construct its tables, Active Record
39
- # handles building the correct aliases and attaching them to its
40
- # JoinDepenencies.
41
- if ::ActiveRecord::VERSION::STRING >= '5.2.3'
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.
42
82
  join_dependency.send(:construct_tables!, join_dependency.send(:join_root))
43
83
  end
44
84
 
@@ -48,17 +88,81 @@ module BabySqueel
48
88
 
49
89
  private
50
90
 
91
+ Associations = ::ActiveRecord::Associations
92
+
51
93
  def find_join_association(associations)
52
94
  current = join_dependency.send(:join_root)
53
95
 
54
96
  associations.each do |association|
55
97
  name = association._reflection.name
56
- current = current.children.find { |c| c.reflection.name == name }
98
+ current = current.children.find { |c| c.reflection.name == name && klass_equal?(association, c) }
57
99
  break if current.nil?
58
100
  end
59
101
 
60
102
  current
61
103
  end
104
+
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
111
+ end
112
+
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
134
+ end
135
+
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
165
+ end
62
166
  end
63
167
  end
64
168
  end
@@ -1,3 +1,3 @@
1
1
  module BabySqueel
2
- VERSION = '1.4.0.beta1'.freeze
2
+ VERSION = '1.4.4'.freeze
3
3
  end
metadata CHANGED
@@ -1,29 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: baby_squeel
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0.beta1
4
+ version: 1.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ray Zane
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-04-21 00:00:00.000000000 Z
11
+ date: 2022-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
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
29
  version: '5.2'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '7.1'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: ransack
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -38,20 +44,6 @@ dependencies:
38
44
  - - "~>"
39
45
  - !ruby/object:Gem::Version
40
46
  version: '2.3'
41
- - !ruby/object:Gem::Dependency
42
- name: join_dependency
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: 0.1.4
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: 0.1.4
55
47
  - !ruby/object:Gem::Dependency
56
48
  name: bundler
57
49
  requirement: !ruby/object:Gem::Requirement
@@ -98,16 +90,16 @@ dependencies:
98
90
  name: sqlite3
99
91
  requirement: !ruby/object:Gem::Requirement
100
92
  requirements:
101
- - - "~>"
93
+ - - ">="
102
94
  - !ruby/object:Gem::Version
103
- version: 1.3.6
95
+ version: '0'
104
96
  type: :development
105
97
  prerelease: false
106
98
  version_requirements: !ruby/object:Gem::Requirement
107
99
  requirements:
108
- - - "~>"
100
+ - - ">="
109
101
  - !ruby/object:Gem::Version
110
- version: 1.3.6
102
+ version: '0'
111
103
  description: An expressive query DSL for Active Record 4 and 5.
112
104
  email:
113
105
  - ray@promptworks.com
@@ -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
@@ -160,11 +152,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
160
152
  version: '0'
161
153
  required_rubygems_version: !ruby/object:Gem::Requirement
162
154
  requirements:
163
- - - ">"
155
+ - - ">="
164
156
  - !ruby/object:Gem::Version
165
- version: 1.3.1
157
+ version: '0'
166
158
  requirements: []
167
- rubygems_version: 3.0.3
159
+ rubygems_version: 3.3.3
168
160
  signing_key:
169
161
  specification_version: 4
170
162
  summary: An expressive query DSL for Active Record 4 and 5.
@@ -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