activerecord 6.1.3.2 → 6.1.4.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +105 -2
  3. data/lib/active_record/associations/association.rb +7 -1
  4. data/lib/active_record/associations/belongs_to_association.rb +1 -2
  5. data/lib/active_record/coders/yaml_column.rb +11 -1
  6. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +1 -1
  7. data/lib/active_record/connection_adapters/abstract/transaction.rb +14 -3
  8. data/lib/active_record/connection_adapters/abstract_adapter.rb +3 -3
  9. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +6 -2
  10. data/lib/active_record/connection_adapters/pool_manager.rb +5 -1
  11. data/lib/active_record/connection_adapters/schema_cache.rb +9 -1
  12. data/lib/active_record/connection_adapters/sql_type_metadata.rb +0 -2
  13. data/lib/active_record/connection_adapters.rb +2 -0
  14. data/lib/active_record/core.rb +16 -5
  15. data/lib/active_record/enum.rb +4 -6
  16. data/lib/active_record/gem_version.rb +2 -2
  17. data/lib/active_record/insert_all.rb +5 -1
  18. data/lib/active_record/railties/databases.rake +3 -2
  19. data/lib/active_record/relation/calculations.rb +6 -2
  20. data/lib/active_record/relation/query_methods.rb +1 -1
  21. data/lib/active_record/relation/where_clause.rb +12 -9
  22. data/lib/active_record/relation.rb +9 -15
  23. data/lib/active_record/scoping/default.rb +1 -3
  24. data/lib/active_record/statement_cache.rb +2 -2
  25. data/lib/active_record/test_fixtures.rb +42 -1
  26. data/lib/active_record/validations/numericality.rb +1 -1
  27. data/lib/arel/collectors/bind.rb +2 -2
  28. data/lib/arel/collectors/composite.rb +3 -3
  29. data/lib/arel/collectors/sql_string.rb +1 -1
  30. data/lib/arel/collectors/substitute_binds.rb +1 -1
  31. data/lib/arel/nodes/homogeneous_in.rb +4 -0
  32. data/lib/arel/predications.rb +2 -2
  33. data/lib/arel/visitors/to_sql.rb +1 -1
  34. metadata +10 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4388f56d55688f1f53d21619c1d97a976a0bf198e46813febbaf7a867fb47702
4
- data.tar.gz: 63314ed55ab0aa06c816b9208764f00a897ec40485c23dc23659ecadf5490d91
3
+ metadata.gz: bfce4c7e3e72a9532c8532e7285191bd87922110c4ae68f5b614f9f760c255a8
4
+ data.tar.gz: ac62553b4d11f238a2f92232b8c5146a239c9afb55a1cee10e013c9b1877b209
5
5
  SHA512:
6
- metadata.gz: d6da5c43903489b203067e4c187ffa405a91d6f35bd0d23087e225b2bc49f9b1ad4e5c4df73f72de8577ed0c044e049b5381a22a0b1c83215b1d3fc3b5b6d4dd
7
- data.tar.gz: 3e3fffe809e00d052c6147b1e373744ac8875abf94c5225289901184447989a998cd953bbc4a0e644feac0eb4fdf33e14071bf48ac8d6b7741bd1aa962a592ea
6
+ metadata.gz: 94bdbb5e730d7975ba11ea7794ee9e7d36a3a8bbd697d95645e1492f521f16db58f75d12ddfa07c5d35a5f8c98c8971bf95a41fb9e0f5b094b34c2f2671f2fa2
7
+ data.tar.gz: 9b94ac51e360a48bcc47b1c9c19a29946729bc6460b9c9f11b760f8edac7f467eb0aed05dcaa30f0baba946ffd4f6dc78f16971c8fb93051b10dd23cd22a17d8
data/CHANGELOG.md CHANGED
@@ -1,3 +1,106 @@
1
+ ## Rails 6.1.4.1 (August 19, 2021) ##
2
+
3
+ * No changes.
4
+
5
+
6
+ ## Rails 6.1.4 (June 24, 2021) ##
7
+
8
+ * Do not try to rollback transactions that failed due to a `ActiveRecord::TransactionRollbackError`.
9
+
10
+ *Jamie McCarthy*
11
+
12
+ * Raise an error if `pool_config` is `nil` in `set_pool_config`.
13
+
14
+ *Eileen M. Uchitelle*
15
+
16
+ * Fix compatibility with `psych >= 4`.
17
+
18
+ Starting in Psych 4.0.0 `YAML.load` behaves like `YAML.safe_load`. To preserve compatibility
19
+ Active Record's schema cache loader and `YAMLColumn` now uses `YAML.unsafe_load` if available.
20
+
21
+ *Jean Boussier*
22
+
23
+ * Support using replicas when using `rails dbconsole`.
24
+
25
+ *Christopher Thornton*
26
+
27
+ * Restore connection pools after transactional tests.
28
+
29
+ *Eugene Kenny*
30
+
31
+ * Change `upsert_all` to fails cleanly for MySQL when `:unique_by` is used.
32
+
33
+ *Bastian Bartmann*
34
+
35
+ * Fix user-defined `self.default_scope` to respect table alias.
36
+
37
+ *Ryuta Kamizono*
38
+
39
+ * Clear `@cache_keys` cache after `update_all`, `delete_all`, `destroy_all`.
40
+
41
+ *Ryuta Kamizono*
42
+
43
+ * Changed Arel predications `contains` and `overlaps` to use
44
+ `quoted_node` so that PostgreSQL arrays are quoted properly.
45
+
46
+ *Bradley Priest*
47
+
48
+ * Fix `merge` when the `where` clauses have string contents.
49
+
50
+ *Ryuta Kamizono*
51
+
52
+ * Fix rollback of parent destruction with nested `dependent: :destroy`.
53
+
54
+ *Jacopo Beschi*
55
+
56
+ * Fix binds logging for `"WHERE ... IN ..."` statements.
57
+
58
+ *Ricardo Díaz*
59
+
60
+ * Handle `false` in relation strict loading checks.
61
+
62
+ Previously when a model had strict loading set to true and then had a
63
+ relation set `strict_loading` to false the false wasn't considered when
64
+ deciding whether to raise/warn about strict loading.
65
+
66
+ ```
67
+ class Dog < ActiveRecord::Base
68
+ self.strict_loading_by_default = true
69
+
70
+ has_many :treats, strict_loading: false
71
+ end
72
+ ```
73
+
74
+ In the example, `dog.treats` would still raise even though
75
+ `strict_loading` was set to false. This is a bug effecting more than
76
+ Active Storage which is why I made this PR superceeding #41461. We need
77
+ to fix this for all applications since the behavior is a little
78
+ surprising. I took the test from ##41461 and the code suggestion from #41453
79
+ with some additions.
80
+
81
+ *Eileen M. Uchitelle*, *Radamés Roriz*
82
+
83
+ * Fix numericality validator without precision.
84
+
85
+ *Ryuta Kamizono*
86
+
87
+ * Fix aggregate attribute on Enum types.
88
+
89
+ *Ryuta Kamizono*
90
+
91
+ * Fix `CREATE INDEX` statement generation for PostgreSQL.
92
+
93
+ *eltongo*
94
+
95
+ * Fix where clause on enum attribute when providing array of strings.
96
+
97
+ *Ryuta Kamizono*
98
+
99
+ * Fix `unprepared_statement` to work it when nesting.
100
+
101
+ *Ryuta Kamizono*
102
+
103
+
1
104
  ## Rails 6.1.3.2 (May 05, 2021) ##
2
105
 
3
106
  * No changes.
@@ -1053,14 +1156,14 @@
1053
1156
  Deprecated behavior:
1054
1157
 
1055
1158
  ```ruby
1056
- db_config = ActiveRecord::Base.configs_for(env_name: "development", spec_name: "primary")
1159
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: "development", spec_name: "primary")
1057
1160
  db_config.spec_name
1058
1161
  ```
1059
1162
 
1060
1163
  New behavior:
1061
1164
 
1062
1165
  ```ruby
1063
- db_config = ActiveRecord::Base.configs_for(env_name: "development", name: "primary")
1166
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: "development", name: "primary")
1064
1167
  db_config.name
1065
1168
  ```
1066
1169
 
@@ -211,7 +211,7 @@ module ActiveRecord
211
211
 
212
212
  private
213
213
  def find_target
214
- if (owner.strict_loading? || reflection.strict_loading?) && owner.validation_context.nil?
214
+ if strict_loading? && owner.validation_context.nil?
215
215
  Base.strict_loading_violation!(owner: owner.class, reflection: reflection)
216
216
  end
217
217
 
@@ -227,6 +227,12 @@ module ActiveRecord
227
227
  sc.execute(binds, klass.connection) { |record| set_inverse_instance(record) }
228
228
  end
229
229
 
230
+ def strict_loading?
231
+ return reflection.strict_loading? if reflection.options.key?(:strict_loading)
232
+
233
+ owner.strict_loading?
234
+ end
235
+
230
236
  # The scope for this association.
231
237
  #
232
238
  # Note that the association_scope is merged into the target_scope only when the
@@ -9,8 +9,7 @@ module ActiveRecord
9
9
 
10
10
  case options[:dependent]
11
11
  when :destroy
12
- target.destroy
13
- raise ActiveRecord::Rollback unless target.destroyed?
12
+ raise ActiveRecord::Rollback unless target.destroy
14
13
  when :destroy_async
15
14
  id = owner.public_send(reflection.foreign_key.to_sym)
16
15
  primary_key_column = reflection.active_record_primary_key.to_sym
@@ -23,7 +23,7 @@ module ActiveRecord
23
23
  def load(yaml)
24
24
  return object_class.new if object_class != Object && yaml.nil?
25
25
  return yaml unless yaml.is_a?(String) && yaml.start_with?("---")
26
- obj = YAML.load(yaml)
26
+ obj = yaml_load(yaml)
27
27
 
28
28
  assert_valid_value(obj, action: "load")
29
29
  obj ||= object_class.new if object_class != Object
@@ -44,6 +44,16 @@ module ActiveRecord
44
44
  rescue ArgumentError
45
45
  raise ArgumentError, "Cannot serialize #{object_class}. Classes passed to `serialize` must have a 0 argument constructor."
46
46
  end
47
+
48
+ if YAML.respond_to?(:unsafe_load)
49
+ def yaml_load(payload)
50
+ YAML.unsafe_load(payload)
51
+ end
52
+ else
53
+ def yaml_load(payload)
54
+ YAML.load(payload)
55
+ end
56
+ end
47
57
  end
48
58
  end
49
59
  end
@@ -94,8 +94,8 @@ module ActiveRecord
94
94
  sql = ["CREATE"]
95
95
  sql << "UNIQUE" if index.unique
96
96
  sql << "INDEX"
97
- sql << "IF NOT EXISTS" if o.if_not_exists
98
97
  sql << o.algorithm if o.algorithm
98
+ sql << "IF NOT EXISTS" if o.if_not_exists
99
99
  sql << index.type if index.type
100
100
  sql << "#{quote_column_name(index.name)} ON #{quote_table_name(index.table)}"
101
101
  sql << "USING #{index.using}" if supports_index_using? && index.using
@@ -33,6 +33,10 @@ module ActiveRecord
33
33
  @state == :fully_rolledback
34
34
  end
35
35
 
36
+ def invalidated?
37
+ @state == :invalidated
38
+ end
39
+
36
40
  def fully_completed?
37
41
  completed?
38
42
  end
@@ -51,6 +55,11 @@ module ActiveRecord
51
55
  @state = :fully_rolledback
52
56
  end
53
57
 
58
+ def invalidate!
59
+ @children&.each { |c| c.invalidate! }
60
+ @state = :invalidated
61
+ end
62
+
54
63
  def commit!
55
64
  @state = :committed
56
65
  end
@@ -299,7 +308,7 @@ module ActiveRecord
299
308
  def rollback_transaction(transaction = nil)
300
309
  @connection.lock.synchronize do
301
310
  transaction ||= @stack.pop
302
- transaction.rollback
311
+ transaction.rollback unless transaction.state.invalidated?
303
312
  transaction.rollback_records
304
313
  end
305
314
  end
@@ -312,15 +321,17 @@ module ActiveRecord
312
321
  ret
313
322
  rescue Exception => error
314
323
  if transaction
324
+ transaction.state.invalidate! if error.is_a? ActiveRecord::TransactionRollbackError
315
325
  rollback_transaction
316
326
  after_failure_actions(transaction, error)
317
327
  end
328
+
318
329
  raise
319
330
  ensure
320
331
  if transaction
321
332
  if error
322
- # @connection still holds an open transaction, so we must not
323
- # put it back in the pool for reuse
333
+ # @connection still holds an open or invalid transaction, so we must not
334
+ # put it back in the pool for reuse.
324
335
  @connection.throw_away! unless transaction.state.rolledback?
325
336
  else
326
337
  if Thread.current.status == "aborting"
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "set"
4
- require "active_record/connection_adapters/schema_cache"
5
4
  require "active_record/connection_adapters/sql_type_metadata"
6
5
  require "active_record/connection_adapters/abstract/schema_dumper"
7
6
  require "active_record/connection_adapters/abstract/schema_creation"
@@ -154,9 +153,10 @@ module ActiveRecord
154
153
  end
155
154
  end
156
155
 
157
- def prepared_statements
156
+ def prepared_statements?
158
157
  @prepared_statements && !prepared_statements_disabled_cache.include?(object_id)
159
158
  end
159
+ alias :prepared_statements :prepared_statements?
160
160
 
161
161
  def prepared_statements_disabled_cache # :nodoc:
162
162
  Thread.current[:ar_prepared_statements_disabled_cache] ||= Set.new
@@ -250,7 +250,7 @@ module ActiveRecord
250
250
  end
251
251
 
252
252
  def unprepared_statement
253
- cache = prepared_statements_disabled_cache.add(object_id) if @prepared_statements
253
+ cache = prepared_statements_disabled_cache.add?(object_id) if @prepared_statements
254
254
  yield
255
255
  ensure
256
256
  cache&.delete(object_id)
@@ -23,8 +23,12 @@ module ActiveRecord
23
23
  @name_to_pool_config[shard]
24
24
  end
25
25
 
26
- def set_pool_config(_, shard, pool_config)
27
- @name_to_pool_config[shard] = pool_config
26
+ def set_pool_config(role, shard, pool_config)
27
+ if pool_config
28
+ @name_to_pool_config[shard] = pool_config
29
+ else
30
+ raise ArgumentError, "The `pool_config` for the :#{role} role and :#{shard} shard was `nil`. Please check your configuration. If you want your writing role to be something other than `:writing` set `config.active_record.writing_role` in your application configuration. The same setting should be applied for the `reading_role` if applicable."
31
+ end
28
32
  end
29
33
  end
30
34
  end
@@ -36,7 +36,11 @@ module ActiveRecord
36
36
  end
37
37
 
38
38
  def set_pool_config(role, shard, pool_config)
39
- @name_to_role_mapping[role][shard] = pool_config
39
+ if pool_config
40
+ @name_to_role_mapping[role][shard] = pool_config
41
+ else
42
+ raise ArgumentError, "The `pool_config` for the :#{role} role and :#{shard} shard was `nil`. Please check your configuration. If you want your writing role to be something other than `:writing` set `config.active_record.writing_role` in your application configuration. The same setting should be applied for the `reading_role` if applicable."
43
+ end
40
44
  end
41
45
  end
42
46
  end
@@ -9,7 +9,15 @@ module ActiveRecord
9
9
  return unless File.file?(filename)
10
10
 
11
11
  read(filename) do |file|
12
- filename.include?(".dump") ? Marshal.load(file) : YAML.load(file)
12
+ if filename.include?(".dump")
13
+ Marshal.load(file)
14
+ else
15
+ if YAML.respond_to?(:unsafe_load)
16
+ YAML.unsafe_load(file)
17
+ else
18
+ YAML.load(file)
19
+ end
20
+ end
13
21
  end
14
22
  end
15
23
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_record/connection_adapters/deduplicable"
4
-
5
3
  module ActiveRecord
6
4
  # :stopdoc:
7
5
  module ConnectionAdapters
@@ -12,6 +12,8 @@ module ActiveRecord
12
12
  autoload :PoolConfig
13
13
  autoload :PoolManager
14
14
  autoload :LegacyPoolManager
15
+ autoload :SchemaCache
16
+ autoload :Deduplicable
15
17
 
16
18
  autoload_at "active_record/connection_adapters/abstract/schema_definitions" do
17
19
  autoload :IndexDefinition
@@ -408,7 +408,21 @@ module ActiveRecord
408
408
  end
409
409
 
410
410
  # Specifies columns which shouldn't be exposed while calling +#inspect+.
411
- attr_writer :filter_attributes
411
+ def filter_attributes=(filter_attributes)
412
+ @inspection_filter = nil
413
+ @filter_attributes = filter_attributes
414
+ end
415
+
416
+ def inspection_filter # :nodoc:
417
+ if defined?(@filter_attributes)
418
+ @inspection_filter ||= begin
419
+ mask = InspectionMask.new(ActiveSupport::ParameterFilter::FILTERED)
420
+ ActiveSupport::ParameterFilter.new(@filter_attributes, mask: mask)
421
+ end
422
+ else
423
+ superclass.inspection_filter
424
+ end
425
+ end
412
426
 
413
427
  # Returns a string like 'Post(id:integer, title:string, body:text)'
414
428
  def inspect # :nodoc:
@@ -776,10 +790,7 @@ module ActiveRecord
776
790
  private_constant :InspectionMask
777
791
 
778
792
  def inspection_filter
779
- @inspection_filter ||= begin
780
- mask = InspectionMask.new(ActiveSupport::ParameterFilter::FILTERED)
781
- ActiveSupport::ParameterFilter.new(self.class.filter_attributes, mask: mask)
782
- end
793
+ self.class.inspection_filter
783
794
  end
784
795
  end
785
796
  end
@@ -139,22 +139,20 @@ module ActiveRecord
139
139
  mapping.key(subtype.deserialize(value))
140
140
  end
141
141
 
142
- def serializable?(value)
143
- (value.blank? || mapping.has_key?(value) || mapping.has_value?(value)) && super
144
- end
145
-
146
142
  def serialize(value)
147
143
  mapping.fetch(value, value)
148
144
  end
149
145
 
150
146
  def assert_valid_value(value)
151
- unless serializable?(value)
147
+ unless value.blank? || mapping.has_key?(value) || mapping.has_value?(value)
152
148
  raise ArgumentError, "'#{value}' is not a valid #{name}"
153
149
  end
154
150
  end
155
151
 
152
+ attr_reader :subtype
153
+
156
154
  private
157
- attr_reader :name, :mapping, :subtype
155
+ attr_reader :name, :mapping
158
156
  end
159
157
 
160
158
  def enum(definitions)
@@ -9,8 +9,8 @@ module ActiveRecord
9
9
  module VERSION
10
10
  MAJOR = 6
11
11
  MINOR = 1
12
- TINY = 3
13
- PRE = "2"
12
+ TINY = 4
13
+ PRE = "1"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -69,7 +69,11 @@ module ActiveRecord
69
69
  attr_reader :scope_attributes
70
70
 
71
71
  def find_unique_index_for(unique_by)
72
- return unique_by if !connection.supports_insert_conflict_target?
72
+ if !connection.supports_insert_conflict_target?
73
+ return if unique_by.nil?
74
+
75
+ raise ArgumentError, "#{connection.class} does not support :unique_by"
76
+ end
73
77
 
74
78
  name_or_columns = unique_by || model.primary_key
75
79
  match = Array(name_or_columns).map(&:to_s)
@@ -413,8 +413,9 @@ db_namespace = namespace :db do
413
413
  fixture_files = if ENV["FIXTURES"]
414
414
  ENV["FIXTURES"].split(",")
415
415
  else
416
- # The use of String#[] here is to support namespaced fixtures.
417
- Dir["#{fixtures_dir}/**/*.yml"].map { |f| f[(fixtures_dir.size + 1)..-5] }
416
+ files = Dir[File.join(fixtures_dir, "**/*.{yml}")]
417
+ files.reject! { |f| f.start_with?(File.join(fixtures_dir, "files")) }
418
+ files.map! { |f| f[fixtures_dir.to_s.size..-5].delete_prefix("/") }
418
419
  end
419
420
 
420
421
  ActiveRecord::FixtureSet.create_fixtures(fixtures_dir, fixture_files)
@@ -310,6 +310,7 @@ module ActiveRecord
310
310
  type_cast_calculated_value(result.cast_values.first, operation) do |value|
311
311
  type = column.try(:type_caster) ||
312
312
  lookup_cast_type_from_join_dependencies(column_name.to_s) || Type.default_value
313
+ type = type.subtype if Enum::EnumType === type
313
314
  type.deserialize(value)
314
315
  end
315
316
  end
@@ -387,8 +388,11 @@ module ActiveRecord
387
388
  key = key_records[key] if associated
388
389
 
389
390
  result[key] = type_cast_calculated_value(row[column_alias], operation) do |value|
390
- type ||= column.try(:type_caster) ||
391
- lookup_cast_type_from_join_dependencies(column_name.to_s) || Type.default_value
391
+ unless type
392
+ type = column.try(:type_caster) ||
393
+ lookup_cast_type_from_join_dependencies(column_name.to_s) || Type.default_value
394
+ type = type.subtype if Enum::EnumType === type
395
+ end
392
396
  type.deserialize(value)
393
397
  end
394
398
  end
@@ -1133,7 +1133,7 @@ module ActiveRecord
1133
1133
  raise ImmutableRelation if defined?(@arel) && @arel
1134
1134
  end
1135
1135
 
1136
- def build_arel(aliases)
1136
+ def build_arel(aliases = nil)
1137
1137
  arel = Arel::SelectManager.new(table)
1138
1138
 
1139
1139
  build_joins(arel.join_sources, aliases)
@@ -103,28 +103,31 @@ module ActiveRecord
103
103
  end
104
104
 
105
105
  def extract_attributes
106
- predicates.each_with_object([]) do |node, attrs|
107
- attr = extract_attribute(node) || begin
108
- node.left if node.equality? && node.left.is_a?(Arel::Predications)
109
- end
110
- attrs << attr if attr
111
- end
106
+ attrs = []
107
+ each_attributes { |attr, _| attrs << attr }
108
+ attrs
112
109
  end
113
110
 
114
111
  protected
115
112
  attr_reader :predicates
116
113
 
117
114
  def referenced_columns
118
- predicates.each_with_object({}) do |node, hash|
115
+ hash = {}
116
+ each_attributes { |attr, node| hash[attr] = node }
117
+ hash
118
+ end
119
+
120
+ private
121
+ def each_attributes
122
+ predicates.each do |node|
119
123
  attr = extract_attribute(node) || begin
120
124
  node.left if equality_node?(node) && node.left.is_a?(Arel::Predications)
121
125
  end
122
126
 
123
- hash[attr] = node if attr
127
+ yield attr, node if attr
124
128
  end
125
129
  end
126
130
 
127
- private
128
131
  def extract_attribute(node)
129
132
  attr_node = nil
130
133
  Arel.fetch_attribute(node) do |attr|
@@ -440,13 +440,11 @@ module ActiveRecord
440
440
  def update_all(updates)
441
441
  raise ArgumentError, "Empty list of attributes to change" if updates.blank?
442
442
 
443
- if eager_loading?
444
- relation = apply_join_dependency
445
- return relation.update_all(updates)
446
- end
443
+ arel = eager_loading? ? apply_join_dependency.arel : build_arel
444
+ arel.source.left = table
447
445
 
448
446
  stmt = Arel::UpdateManager.new
449
- stmt.table(arel.join_sources.empty? ? table : arel.source)
447
+ stmt.table(arel.source)
450
448
  stmt.key = table[primary_key]
451
449
  stmt.take(arel.limit)
452
450
  stmt.offset(arel.offset)
@@ -465,7 +463,7 @@ module ActiveRecord
465
463
  stmt.set Arel.sql(klass.sanitize_sql_for_assignment(updates, table.name))
466
464
  end
467
465
 
468
- @klass.connection.update stmt, "#{@klass} Update All"
466
+ klass.connection.update(stmt, "#{klass} Update All").tap { reset }
469
467
  end
470
468
 
471
469
  def update(id = :all, attributes) # :nodoc:
@@ -582,23 +580,18 @@ module ActiveRecord
582
580
  raise ActiveRecordError.new("delete_all doesn't support #{invalid_methods.join(', ')}")
583
581
  end
584
582
 
585
- if eager_loading?
586
- relation = apply_join_dependency
587
- return relation.delete_all
588
- end
583
+ arel = eager_loading? ? apply_join_dependency.arel : build_arel
584
+ arel.source.left = table
589
585
 
590
586
  stmt = Arel::DeleteManager.new
591
- stmt.from(arel.join_sources.empty? ? table : arel.source)
587
+ stmt.from(arel.source)
592
588
  stmt.key = table[primary_key]
593
589
  stmt.take(arel.limit)
594
590
  stmt.offset(arel.offset)
595
591
  stmt.order(*arel.orders)
596
592
  stmt.wheres = arel.constraints
597
593
 
598
- affected = @klass.connection.delete(stmt, "#{@klass} Destroy")
599
-
600
- reset
601
- affected
594
+ klass.connection.delete(stmt, "#{klass} Destroy").tap { reset }
602
595
  end
603
596
 
604
597
  # Finds and destroys all records matching the specified conditions.
@@ -652,6 +645,7 @@ module ActiveRecord
652
645
  @delegate_to_klass = false
653
646
  @to_sql = @arel = @loaded = @should_eager_load = nil
654
647
  @offsets = @take = nil
648
+ @cache_keys = nil
655
649
  @records = [].freeze
656
650
  self
657
651
  end
@@ -109,9 +109,7 @@ module ActiveRecord
109
109
  if default_scope_override
110
110
  # The user has defined their own default scope method, so call that
111
111
  evaluate_default_scope do
112
- if scope = default_scope
113
- relation.merge!(scope)
114
- end
112
+ relation.scoping { default_scope }
115
113
  end
116
114
  elsif default_scopes.any?
117
115
  evaluate_default_scope do
@@ -80,8 +80,8 @@ module ActiveRecord
80
80
  self
81
81
  end
82
82
 
83
- def add_binds(binds)
84
- @binds.concat binds
83
+ def add_binds(binds, proc_for_binds = nil)
84
+ @binds.concat proc_for_binds ? binds.map(&proc_for_binds) : binds
85
85
  binds.size.times do |i|
86
86
  @parts << ", " unless i == 0
87
87
  @parts << Substitute.new
@@ -111,6 +111,8 @@ module ActiveRecord
111
111
  @fixture_connections = []
112
112
  @@already_loaded_fixtures ||= {}
113
113
  @connection_subscriber = nil
114
+ @legacy_saved_pool_configs = Hash.new { |hash, key| hash[key] = {} }
115
+ @saved_pool_configs = Hash.new { |hash, key| hash[key] = {} }
114
116
 
115
117
  # Load fixtures once and begin transaction.
116
118
  if run_in_transaction?
@@ -169,6 +171,7 @@ module ActiveRecord
169
171
  connection.pool.lock_thread = false
170
172
  end
171
173
  @fixture_connections.clear
174
+ teardown_shared_connection_pool
172
175
  else
173
176
  ActiveRecord::FixtureSet.reset_cache
174
177
  end
@@ -200,8 +203,13 @@ module ActiveRecord
200
203
  return unless writing_pool_manager
201
204
 
202
205
  pool_manager = handler.send(:owner_to_pool_manager)[name]
206
+ @legacy_saved_pool_configs[handler][name] ||= {}
203
207
  pool_manager.shard_names.each do |shard_name|
204
208
  writing_pool_config = writing_pool_manager.get_pool_config(nil, shard_name)
209
+ pool_config = pool_manager.get_pool_config(nil, shard_name)
210
+ next if pool_config == writing_pool_config
211
+
212
+ @legacy_saved_pool_configs[handler][name][shard_name] = pool_config
205
213
  pool_manager.set_pool_config(nil, shard_name, writing_pool_config)
206
214
  end
207
215
  end
@@ -214,8 +222,12 @@ module ActiveRecord
214
222
  pool_manager = handler.send(:owner_to_pool_manager)[name]
215
223
  pool_manager.shard_names.each do |shard_name|
216
224
  writing_pool_config = pool_manager.get_pool_config(ActiveRecord::Base.writing_role, shard_name)
225
+ @saved_pool_configs[name][shard_name] ||= {}
217
226
  pool_manager.role_names.each do |role|
218
- next unless pool_manager.get_pool_config(role, shard_name)
227
+ next unless pool_config = pool_manager.get_pool_config(role, shard_name)
228
+ next if pool_config == writing_pool_config
229
+
230
+ @saved_pool_configs[name][shard_name][role] = pool_config
219
231
  pool_manager.set_pool_config(role, shard_name, writing_pool_config)
220
232
  end
221
233
  end
@@ -223,6 +235,35 @@ module ActiveRecord
223
235
  end
224
236
  end
225
237
 
238
+ def teardown_shared_connection_pool
239
+ if ActiveRecord::Base.legacy_connection_handling
240
+ @legacy_saved_pool_configs.each_pair do |handler, names|
241
+ names.each_pair do |name, shards|
242
+ shards.each_pair do |shard_name, pool_config|
243
+ pool_manager = handler.send(:owner_to_pool_manager)[name]
244
+ pool_manager.set_pool_config(nil, shard_name, pool_config)
245
+ end
246
+ end
247
+ end
248
+ else
249
+ handler = ActiveRecord::Base.connection_handler
250
+
251
+ @saved_pool_configs.each_pair do |name, shards|
252
+ pool_manager = handler.send(:owner_to_pool_manager)[name]
253
+ shards.each_pair do |shard_name, roles|
254
+ roles.each_pair do |role, pool_config|
255
+ next unless pool_manager.get_pool_config(role, shard_name)
256
+
257
+ pool_manager.set_pool_config(role, shard_name, pool_config)
258
+ end
259
+ end
260
+ end
261
+ end
262
+
263
+ @legacy_saved_pool_configs.clear
264
+ @saved_pool_configs.clear
265
+ end
266
+
226
267
  def load_fixtures(config)
227
268
  ActiveRecord::FixtureSet.create_fixtures(fixture_path, fixture_table_names, fixture_class_names, config).index_by(&:name)
228
269
  end
@@ -4,7 +4,7 @@ module ActiveRecord
4
4
  module Validations
5
5
  class NumericalityValidator < ActiveModel::Validations::NumericalityValidator # :nodoc:
6
6
  def validate_each(record, attribute, value, precision: nil, scale: nil)
7
- precision = [column_precision_for(record, attribute) || BigDecimal.double_fig, BigDecimal.double_fig].min
7
+ precision = [column_precision_for(record, attribute) || Float::DIG, Float::DIG].min
8
8
  scale = column_scale_for(record, attribute)
9
9
  super(record, attribute, value, precision: precision, scale: scale)
10
10
  end
@@ -16,8 +16,8 @@ module Arel # :nodoc: all
16
16
  self
17
17
  end
18
18
 
19
- def add_binds(binds)
20
- @binds.concat binds
19
+ def add_binds(binds, proc_for_binds = nil)
20
+ @binds.concat proc_for_binds ? binds.map(&proc_for_binds) : binds
21
21
  self
22
22
  end
23
23
 
@@ -22,9 +22,9 @@ module Arel # :nodoc: all
22
22
  self
23
23
  end
24
24
 
25
- def add_binds(binds, &block)
26
- left.add_binds(binds, &block)
27
- right.add_binds(binds, &block)
25
+ def add_binds(binds, proc_for_binds = nil, &block)
26
+ left.add_binds(binds, proc_for_binds, &block)
27
+ right.add_binds(binds, proc_for_binds, &block)
28
28
  self
29
29
  end
30
30
 
@@ -18,7 +18,7 @@ module Arel # :nodoc: all
18
18
  self
19
19
  end
20
20
 
21
- def add_binds(binds, &block)
21
+ def add_binds(binds, proc_for_binds = nil, &block)
22
22
  self << (@bind_index...@bind_index += binds.size).map(&block).join(", ")
23
23
  self
24
24
  end
@@ -20,7 +20,7 @@ module Arel # :nodoc: all
20
20
  self << quoter.quote(bind)
21
21
  end
22
22
 
23
- def add_binds(binds)
23
+ def add_binds(binds, proc_for_binds = nil)
24
24
  self << binds.map { |bind| quoter.quote(bind) }.join(", ")
25
25
  end
26
26
 
@@ -55,6 +55,10 @@ module Arel # :nodoc: all
55
55
  casted_values
56
56
  end
57
57
 
58
+ def proc_for_binds
59
+ -> value { ActiveModel::Attribute.with_cast_value(attribute.name, value, attribute.type_caster) }
60
+ end
61
+
58
62
  def fetch_attribute(&block)
59
63
  if attribute
60
64
  yield attribute
@@ -207,11 +207,11 @@ module Arel # :nodoc: all
207
207
  end
208
208
 
209
209
  def contains(other)
210
- Arel::Nodes::Contains.new(self, other)
210
+ Arel::Nodes::Contains.new self, quoted_node(other)
211
211
  end
212
212
 
213
213
  def overlaps(other)
214
- Arel::Nodes::Overlaps.new(self, other)
214
+ Arel::Nodes::Overlaps.new self, quoted_node(other)
215
215
  end
216
216
 
217
217
  def quoted_array(others)
@@ -337,7 +337,7 @@ module Arel # :nodoc: all
337
337
  if values.empty?
338
338
  collector << @connection.quote(nil)
339
339
  else
340
- collector.add_binds(values, &bind_block)
340
+ collector.add_binds(values, o.proc_for_binds, &bind_block)
341
341
  end
342
342
 
343
343
  collector << ")"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.1.3.2
4
+ version: 6.1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-05 00:00:00.000000000 Z
11
+ date: 2021-08-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 6.1.3.2
19
+ version: 6.1.4.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 6.1.3.2
26
+ version: 6.1.4.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activemodel
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 6.1.3.2
33
+ version: 6.1.4.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 6.1.3.2
40
+ version: 6.1.4.1
41
41
  description: Databases on Rails. Build a persistent domain model by mapping database
42
42
  tables to Ruby classes. Strong conventions for associations, validations, aggregations,
43
43
  migrations, and testing come baked-in.
@@ -390,10 +390,10 @@ licenses:
390
390
  - MIT
391
391
  metadata:
392
392
  bug_tracker_uri: https://github.com/rails/rails/issues
393
- changelog_uri: https://github.com/rails/rails/blob/v6.1.3.2/activerecord/CHANGELOG.md
394
- documentation_uri: https://api.rubyonrails.org/v6.1.3.2/
393
+ changelog_uri: https://github.com/rails/rails/blob/v6.1.4.1/activerecord/CHANGELOG.md
394
+ documentation_uri: https://api.rubyonrails.org/v6.1.4.1/
395
395
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
396
- source_code_uri: https://github.com/rails/rails/tree/v6.1.3.2/activerecord
396
+ source_code_uri: https://github.com/rails/rails/tree/v6.1.4.1/activerecord
397
397
  post_install_message:
398
398
  rdoc_options:
399
399
  - "--main"
@@ -411,7 +411,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
411
411
  - !ruby/object:Gem::Version
412
412
  version: '0'
413
413
  requirements: []
414
- rubygems_version: 3.1.2
414
+ rubygems_version: 3.2.15
415
415
  signing_key:
416
416
  specification_version: 4
417
417
  summary: Object-relational mapper framework (part of Rails).