activerecord 6.1.0 → 6.1.3

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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +195 -15
  3. data/README.rdoc +1 -1
  4. data/lib/active_record/aggregations.rb +4 -4
  5. data/lib/active_record/association_relation.rb +10 -0
  6. data/lib/active_record/associations/association.rb +7 -7
  7. data/lib/active_record/associations/association_scope.rb +7 -5
  8. data/lib/active_record/associations/belongs_to_association.rb +7 -3
  9. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -2
  10. data/lib/active_record/associations/builder/association.rb +23 -2
  11. data/lib/active_record/associations/builder/belongs_to.rb +2 -2
  12. data/lib/active_record/associations/has_many_association.rb +1 -1
  13. data/lib/active_record/associations/join_dependency/join_association.rb +8 -7
  14. data/lib/active_record/associations/join_dependency.rb +1 -1
  15. data/lib/active_record/associations.rb +6 -2
  16. data/lib/active_record/attributes.rb +1 -1
  17. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +4 -4
  18. data/lib/active_record/connection_adapters/abstract/database_statements.rb +1 -1
  19. data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
  20. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +4 -0
  21. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +7 -1
  22. data/lib/active_record/connection_adapters/abstract_adapter.rb +7 -8
  23. data/lib/active_record/connection_adapters/mysql/quoting.rb +17 -2
  24. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +4 -1
  25. data/lib/active_record/connection_adapters/pool_config.rb +13 -3
  26. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +1 -1
  27. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  28. data/lib/active_record/connection_adapters/postgresql_adapter.rb +2 -8
  29. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -1
  30. data/lib/active_record/connection_handling.rb +20 -12
  31. data/lib/active_record/core.rb +42 -24
  32. data/lib/active_record/database_configurations/url_config.rb +1 -1
  33. data/lib/active_record/enum.rb +48 -28
  34. data/lib/active_record/fixtures.rb +5 -2
  35. data/lib/active_record/gem_version.rb +1 -1
  36. data/lib/active_record/locking/optimistic.rb +14 -4
  37. data/lib/active_record/log_subscriber.rb +3 -2
  38. data/lib/active_record/migration/compatibility.rb +2 -1
  39. data/lib/active_record/migration.rb +1 -1
  40. data/lib/active_record/model_schema.rb +4 -4
  41. data/lib/active_record/railties/console_sandbox.rb +2 -4
  42. data/lib/active_record/railties/databases.rake +13 -7
  43. data/lib/active_record/reflection.rb +1 -1
  44. data/lib/active_record/relation/finder_methods.rb +1 -1
  45. data/lib/active_record/relation/predicate_builder/association_query_value.rb +3 -3
  46. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +9 -5
  47. data/lib/active_record/relation/predicate_builder.rb +5 -6
  48. data/lib/active_record/relation/query_methods.rb +8 -5
  49. data/lib/active_record/relation/where_clause.rb +5 -5
  50. data/lib/active_record/relation.rb +1 -2
  51. data/lib/active_record/signed_id.rb +1 -1
  52. data/lib/active_record/table_metadata.rb +6 -3
  53. data/lib/active_record/tasks/database_tasks.rb +1 -0
  54. data/lib/active_record/transactions.rb +4 -2
  55. metadata +13 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 418812373f3ff5fd16133fe0928b94b80b78b8a366abfc23a205fcb2ccc5a3e3
4
- data.tar.gz: 70db1902a8fc82b1c46f8a7731ffb358357bc8cac29564a57881a732dbd2a65a
3
+ metadata.gz: 6cdd6094f92ff2d3eef67e5ab7f2a8e2a327fbdffaa1f20182fb5bdb7c803685
4
+ data.tar.gz: 197e68aa68f0946e9fcd55c7f0c2f41c237777c893b20a3a00affddbcaa1f367
5
5
  SHA512:
6
- metadata.gz: 31ae64f629cb62f63bc37c74a888d557f9f0b102d401f2f9cf62c7d31655d99e5161ae9bc7f8be874c7a9cf27ec879dde3c04075df5cb2b5868891c0db144a50
7
- data.tar.gz: cfc9585f3a6f53187707a9d96503269e3d4b1c5f1fe8c5f4db3bdefe8ce636042b6cf1fe9fb233491d1e8197f52293a7018a2f9925f1e34644ad1e30b134d59f
6
+ metadata.gz: 4b9b18c89048afe658359cd16b4c13c3a1eb87c8dacae3beeaf99338e2e441f64fd96bf569697cd581ea35f3068f33ee7872f733570f621a774c92b04253dc5e
7
+ data.tar.gz: 4d47d251881e21878596707b1d759f40b8b83a02e759cb1af79d8293498251a6ff3f5b11e4ecdc004ac282c6fc84437bcc60469bf0ed0a880aae1e820e20d4a1
data/CHANGELOG.md CHANGED
@@ -1,3 +1,183 @@
1
+ ## Rails 6.1.3 (February 17, 2021) ##
2
+
3
+ * Fix the MySQL adapter to always set the right collation and charset
4
+ to the connection session.
5
+
6
+ *Rafael Mendonça França*
7
+
8
+ * Fix MySQL adapter handling of time objects when prepared statements
9
+ are enabled.
10
+
11
+ *Rafael Mendonça França*
12
+
13
+ * Fix scoping in enum fields using conditions that would generate
14
+ an `IN` clause.
15
+
16
+ *Ryuta Kamizono*
17
+
18
+ * Skip optimised #exist? query when #include? is called on a relation
19
+ with a having clause
20
+
21
+ Relations that have aliased select values AND a having clause that
22
+ references an aliased select value would generate an error when
23
+ #include? was called, due to an optimisation that would generate
24
+ call #exists? on the relation instead, which effectively alters
25
+ the select values of the query (and thus removes the aliased select
26
+ values), but leaves the having clause intact. Because the having
27
+ clause is then referencing an aliased column that is no longer
28
+ present in the simplified query, an ActiveRecord::InvalidStatement
29
+ error was raised.
30
+
31
+ An sample query affected by this problem:
32
+
33
+ ```ruby
34
+ Author.select('COUNT(*) as total_posts', 'authors.*')
35
+ .joins(:posts)
36
+ .group(:id)
37
+ .having('total_posts > 2')
38
+ .include?(Author.first)
39
+ ```
40
+
41
+ This change adds an addition check to the condition that skips the
42
+ simplified #exists? query, which simply checks for the presence of
43
+ a having clause.
44
+
45
+ Fixes #41417
46
+
47
+ *Michael Smart*
48
+
49
+ * Increment postgres prepared statement counter before making a prepared statement, so if the statement is aborted
50
+ without Rails knowledge (e.g., if app gets kill -9d during long-running query or due to Rack::Timeout), app won't end
51
+ up in perpetual crash state for being inconsistent with Postgres.
52
+
53
+ *wbharding*, *Martin Tepper*
54
+
55
+
56
+ ## Rails 6.1.2.1 (February 10, 2021) ##
57
+
58
+ * Fix possible DoS vector in PostgreSQL money type
59
+
60
+ Carefully crafted input can cause a DoS via the regular expressions used
61
+ for validating the money format in the PostgreSQL adapter. This patch
62
+ fixes the regexp.
63
+
64
+ Thanks to @dee-see from Hackerone for this patch!
65
+
66
+ [CVE-2021-22880]
67
+
68
+ *Aaron Patterson*
69
+
70
+
71
+ ## Rails 6.1.2 (February 09, 2021) ##
72
+
73
+ * Fix timestamp type for sqlite3.
74
+
75
+ *Eileen M. Uchitelle*
76
+
77
+ * Make destroy async transactional.
78
+
79
+ An active record rollback could occur while enqueuing a job. In this
80
+ case the job would enqueue even though the database deletion
81
+ rolledback putting things in a funky state.
82
+
83
+ Now the jobs are only enqueued until after the db transaction has been committed.
84
+
85
+ *Cory Gwin*
86
+
87
+ * Fix malformed packet error in MySQL statement for connection configuration.
88
+
89
+ *robinroestenburg*
90
+
91
+ * Connection specification now passes the "url" key as a configuration for the
92
+ adapter if the "url" protocol is "jdbc", "http", or "https". Previously only
93
+ urls with the "jdbc" prefix were passed to the Active Record Adapter, others
94
+ are assumed to be adapter specification urls.
95
+
96
+ Fixes #41137.
97
+
98
+ *Jonathan Bracy*
99
+
100
+ * Fix granular connection swapping when there are multiple abstract classes.
101
+
102
+ *Eileen M. Uchitelle*
103
+
104
+ * Fix `find_by` with custom primary key for belongs_to association.
105
+
106
+ *Ryuta Kamizono*
107
+
108
+ * Add support for `rails console --sandbox` for multiple database applications.
109
+
110
+ *alpaca-tc*
111
+
112
+ * Fix `where` on polymorphic association with empty array.
113
+
114
+ *Ryuta Kamizono*
115
+
116
+ * Fix preventing writes for `ApplicationRecord`.
117
+
118
+ *Eileen M. Uchitelle*
119
+
120
+
121
+ ## Rails 6.1.1 (January 07, 2021) ##
122
+
123
+ * Fix fixtures loading when strict loading is enabled for the association.
124
+
125
+ *Alex Ghiculescu*
126
+
127
+ * Fix `where` with custom primary key for belongs_to association.
128
+
129
+ *Ryuta Kamizono*
130
+
131
+ * Fix `where` with aliased associations.
132
+
133
+ *Ryuta Kamizono*
134
+
135
+ * Fix `composed_of` with symbol mapping.
136
+
137
+ *Ryuta Kamizono*
138
+
139
+ * Don't skip money's type cast for pluck and calculations.
140
+
141
+ *Ryuta Kamizono*
142
+
143
+ * Fix `where` on polymorphic association with non Active Record object.
144
+
145
+ *Ryuta Kamizono*
146
+
147
+ * Make sure `db:prepare` works even the schema file doesn't exist.
148
+
149
+ *Rafael Mendonça França*
150
+
151
+ * Fix complicated `has_many :through` with nested where condition.
152
+
153
+ *Ryuta Kamizono*
154
+
155
+ * Handle STI models for `has_many dependent: :destroy_async`.
156
+
157
+ *Muhammad Usman*
158
+
159
+ * Restore possibility of passing `false` to :polymorphic option of `belongs_to`.
160
+
161
+ Previously, passing `false` would trigger the option validation logic
162
+ to throw an error saying :polymorphic would not be a valid option.
163
+
164
+ *glaszig*
165
+
166
+ * Allow adding nonnamed expression indexes to be revertible.
167
+
168
+ Fixes #40732.
169
+
170
+ Previously, the following code would raise an error, when executed while rolling back,
171
+ and the index name should be specified explicitly. Now, the index name is inferred
172
+ automatically.
173
+
174
+ ```ruby
175
+ add_index(:items, "to_tsvector('english', description)")
176
+ ```
177
+
178
+ *fatkodima*
179
+
180
+
1
181
  ## Rails 6.1.0 (December 09, 2020) ##
2
182
 
3
183
  * Only warn about negative enums if a positive form that would cause conflicts exists.
@@ -38,21 +218,21 @@
38
218
 
39
219
  Before:
40
220
 
41
- AnimalsRecord.connected_to(role: :reading) do
42
- MealsRecord.connected_to(role: :reading) do
43
- Dog.first # read from animals replica
44
- Dinner.first # read from meals replica
45
- Person.first # read from primary writer
221
+ AnimalsRecord.connected_to(role: :reading) do
222
+ MealsRecord.connected_to(role: :reading) do
223
+ Dog.first # read from animals replica
224
+ Dinner.first # read from meals replica
225
+ Person.first # read from primary writer
226
+ end
46
227
  end
47
- end
48
228
 
49
229
  After:
50
230
 
51
- ActiveRecord::Base.connected_to_many([AnimalsRecord, MealsRecord], role: :reading) do
52
- Dog.first # read from animals replica
53
- Dinner.first # read from meals replica
54
- Person.first # read from primary writer
55
- end
231
+ ActiveRecord::Base.connected_to_many([AnimalsRecord, MealsRecord], role: :reading) do
232
+ Dog.first # read from animals replica
233
+ Dinner.first # read from meals replica
234
+ Person.first # read from primary writer
235
+ end
56
236
 
57
237
  *Eileen M. Uchitelle*, *John Crepezzi*
58
238
 
@@ -170,13 +350,13 @@
170
350
 
171
351
  Before:
172
352
 
173
- User.where.not(name: "Jon", role: "admin")
174
- # SELECT * FROM users WHERE name != 'Jon' AND role != 'admin'
353
+ User.where.not(name: "Jon", role: "admin")
354
+ # SELECT * FROM users WHERE name != 'Jon' AND role != 'admin'
175
355
 
176
356
  After:
177
357
 
178
- User.where.not(name: "Jon", role: "admin")
179
- # SELECT * FROM users WHERE NOT (name == 'Jon' AND role == 'admin')
358
+ User.where.not(name: "Jon", role: "admin")
359
+ # SELECT * FROM users WHERE NOT (name == 'Jon' AND role == 'admin')
180
360
 
181
361
  *Rafael Mendonça França*
182
362
 
data/README.rdoc CHANGED
@@ -194,7 +194,7 @@ The latest version of Active Record can be installed with RubyGems:
194
194
 
195
195
  Source code can be downloaded as part of the Rails project on GitHub:
196
196
 
197
- * https://github.com/rails/rails/tree/master/activerecord
197
+ * https://github.com/rails/rails/tree/main/activerecord
198
198
 
199
199
 
200
200
  == License
@@ -244,8 +244,8 @@ module ActiveRecord
244
244
  private
245
245
  def reader_method(name, class_name, mapping, allow_nil, constructor)
246
246
  define_method(name) do
247
- if @aggregation_cache[name].nil? && (!allow_nil || mapping.any? { |key, _| !_read_attribute(key).nil? })
248
- attrs = mapping.collect { |key, _| _read_attribute(key) }
247
+ if @aggregation_cache[name].nil? && (!allow_nil || mapping.any? { |key, _| !read_attribute(key).nil? })
248
+ attrs = mapping.collect { |key, _| read_attribute(key) }
249
249
  object = constructor.respond_to?(:call) ?
250
250
  constructor.call(*attrs) :
251
251
  class_name.constantize.send(constructor, *attrs)
@@ -271,10 +271,10 @@ module ActiveRecord
271
271
  end
272
272
 
273
273
  if part.nil? && allow_nil
274
- mapping.each { |key, _| self[key] = nil }
274
+ mapping.each { |key, _| write_attribute(key, nil) }
275
275
  @aggregation_cache[name] = nil
276
276
  else
277
- mapping.each { |key, value| self[key] = part.send(value) }
277
+ mapping.each { |key, value| write_attribute(key, part.send(value)) }
278
278
  @aggregation_cache[name] = part.freeze
279
279
  end
280
280
  end
@@ -27,6 +27,16 @@ module ActiveRecord
27
27
  RUBY
28
28
  end
29
29
 
30
+ def build(attributes = nil, &block)
31
+ if attributes.is_a?(Array)
32
+ attributes.collect { |attr| build(attr, &block) }
33
+ else
34
+ block = current_scope_restoring_block(&block)
35
+ scoping { _new(attributes, &block) }
36
+ end
37
+ end
38
+ alias new build
39
+
30
40
  private
31
41
  def _new(attributes, &block)
32
42
  @association.build(attributes, &block)
@@ -211,12 +211,8 @@ module ActiveRecord
211
211
 
212
212
  private
213
213
  def find_target
214
- if owner.strict_loading? && owner.validation_context.nil?
215
- Base.strict_loading_violation!(owner: owner.class, association: klass)
216
- end
217
-
218
- if reflection.strict_loading? && owner.validation_context.nil?
219
- Base.strict_loading_violation!(owner: owner.class, association: reflection.name)
214
+ if (owner.strict_loading? || reflection.strict_loading?) && owner.validation_context.nil?
215
+ Base.strict_loading_violation!(owner: owner.class, reflection: reflection)
220
216
  end
221
217
 
222
218
  scope = self.scope
@@ -331,7 +327,11 @@ module ActiveRecord
331
327
  end
332
328
 
333
329
  def enqueue_destroy_association(options)
334
- owner.class.destroy_association_async_job&.perform_later(**options)
330
+ job_class = owner.class.destroy_association_async_job
331
+
332
+ if job_class
333
+ owner._after_commit_jobs.push([job_class, options])
334
+ end
335
335
  end
336
336
 
337
337
  def inversable?(record)
@@ -131,11 +131,13 @@ module ActiveRecord
131
131
  if scope_chain_item == chain_head.scope
132
132
  scope.merge! item.except(:where, :includes, :unscope, :order)
133
133
  elsif !item.references_values.empty?
134
- join_dependency = item.construct_join_dependency(
135
- item.eager_load_values | item.includes_values, Arel::Nodes::OuterJoin
136
- )
137
- scope.joins!(*item.joins_values, join_dependency)
138
- scope.left_outer_joins!(*item.left_outer_joins_values)
134
+ scope.merge! item.only(:joins, :left_outer_joins)
135
+
136
+ associations = item.eager_load_values | item.includes_values
137
+
138
+ unless associations.empty?
139
+ scope.joins! item.construct_join_dependency(associations, Arel::Nodes::OuterJoin)
140
+ end
139
141
  end
140
142
 
141
143
  reflection.all_includes do
@@ -80,7 +80,7 @@ module ActiveRecord
80
80
  @updated = true
81
81
  end
82
82
 
83
- replace_keys(record)
83
+ replace_keys(record, force: true)
84
84
 
85
85
  self.target = record
86
86
  end
@@ -108,8 +108,12 @@ module ActiveRecord
108
108
  reflection.counter_cache_column && owner.persisted?
109
109
  end
110
110
 
111
- def replace_keys(record)
112
- owner[reflection.foreign_key] = record ? record._read_attribute(primary_key(record.class)) : nil
111
+ def replace_keys(record, force: false)
112
+ target_key = record ? record._read_attribute(primary_key(record.class)) : nil
113
+
114
+ if force || owner[reflection.foreign_key] != target_key
115
+ owner[reflection.foreign_key] = target_key
116
+ end
113
117
  end
114
118
 
115
119
  def primary_key(klass)
@@ -14,9 +14,14 @@ module ActiveRecord
14
14
  end
15
15
 
16
16
  private
17
- def replace_keys(record)
17
+ def replace_keys(record, force: false)
18
18
  super
19
- owner[reflection.foreign_type] = record ? record.class.polymorphic_name : nil
19
+
20
+ target_type = record ? record.class.polymorphic_name : nil
21
+
22
+ if force || owner[reflection.foreign_type] != target_type
23
+ owner[reflection.foreign_type] = target_type
24
+ end
20
25
  end
21
26
 
22
27
  def inverse_reflection_for(record)
@@ -76,6 +76,7 @@ module ActiveRecord::Associations::Builder # :nodoc:
76
76
  if dependent = reflection.options[:dependent]
77
77
  check_dependent_options(dependent, model)
78
78
  add_destroy_callbacks(model, reflection)
79
+ add_after_commit_jobs_callback(model, dependent)
79
80
  end
80
81
 
81
82
  Association.extensions.each do |extension|
@@ -132,11 +133,31 @@ module ActiveRecord::Associations::Builder # :nodoc:
132
133
 
133
134
  def self.add_destroy_callbacks(model, reflection)
134
135
  name = reflection.name
135
- model.before_destroy lambda { |o| o.association(name).handle_dependency }
136
+ model.before_destroy(->(o) { o.association(name).handle_dependency })
137
+ end
138
+
139
+ def self.add_after_commit_jobs_callback(model, dependent)
140
+ if dependent == :destroy_async
141
+ mixin = model.generated_association_methods
142
+
143
+ unless mixin.method_defined?(:_after_commit_jobs)
144
+ model.after_commit(-> do
145
+ _after_commit_jobs.each do |job_class, job_arguments|
146
+ job_class.perform_later(**job_arguments)
147
+ end
148
+ end)
149
+
150
+ mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
151
+ def _after_commit_jobs
152
+ @_after_commit_jobs ||= []
153
+ end
154
+ CODE
155
+ end
156
+ end
136
157
  end
137
158
 
138
159
  private_class_method :build_scope, :macro, :valid_options, :validate_options, :define_extensions,
139
160
  :define_callbacks, :define_accessors, :define_readers, :define_writers, :define_validations,
140
- :valid_dependent_options, :check_dependent_options, :add_destroy_callbacks
161
+ :valid_dependent_options, :check_dependent_options, :add_destroy_callbacks, :add_after_commit_jobs_callback
141
162
  end
142
163
  end
@@ -7,8 +7,8 @@ module ActiveRecord::Associations::Builder # :nodoc:
7
7
  end
8
8
 
9
9
  def self.valid_options(options)
10
- valid = super + [:counter_cache, :optional, :default]
11
- valid += [:polymorphic, :foreign_type] if options[:polymorphic]
10
+ valid = super + [:polymorphic, :counter_cache, :optional, :default]
11
+ valid += [:foreign_type] if options[:polymorphic]
12
12
  valid += [:ensuring_owner_was] if options[:dependent] == :destroy_async
13
13
  valid
14
14
  end
@@ -42,7 +42,7 @@ module ActiveRecord
42
42
  enqueue_destroy_association(
43
43
  owner_model_name: owner.class.to_s,
44
44
  owner_id: owner.id,
45
- association_class: association_class.to_s,
45
+ association_class: reflection.klass.to_s,
46
46
  association_ids: ids,
47
47
  association_primary_key_column: primary_key_column,
48
48
  ensuring_owner_was_method: options.fetch(:ensuring_owner_was, nil)
@@ -42,16 +42,17 @@ module ActiveRecord
42
42
  chain.reverse_each do |reflection, table|
43
43
  klass = reflection.klass
44
44
 
45
- join_scope = reflection.join_scope(table, foreign_table, foreign_klass)
45
+ scope = reflection.join_scope(table, foreign_table, foreign_klass)
46
46
 
47
- unless join_scope.references_values.empty?
48
- join_dependency = join_scope.construct_join_dependency(
49
- join_scope.eager_load_values | join_scope.includes_values, Arel::Nodes::OuterJoin
50
- )
51
- join_scope.joins!(join_dependency)
47
+ unless scope.references_values.empty?
48
+ associations = scope.eager_load_values | scope.includes_values
49
+
50
+ unless associations.empty?
51
+ scope.joins! scope.construct_join_dependency(associations, Arel::Nodes::OuterJoin)
52
+ end
52
53
  end
53
54
 
54
- arel = join_scope.arel(alias_tracker.aliases)
55
+ arel = scope.arel(alias_tracker.aliases)
55
56
  nodes = arel.constraints.first
56
57
 
57
58
  if nodes.is_a?(Arel::Nodes::And)
@@ -195,7 +195,7 @@ module ActiveRecord
195
195
  next table, true
196
196
  end
197
197
 
198
- table_name = @references[reflection.name.to_sym]
198
+ table_name = @references[reflection.name.to_sym]&.to_s
199
199
 
200
200
  table = alias_tracker.aliased_table_for(reflection.klass.arel_table, table_name) do
201
201
  name = reflection.alias_candidate(parent.table_name)
@@ -1371,7 +1371,9 @@ module ActiveRecord
1371
1371
  #
1372
1372
  # * <tt>nil</tt> do nothing (default).
1373
1373
  # * <tt>:destroy</tt> causes all the associated objects to also be destroyed.
1374
- # * <tt>:destroy_async</tt> destroys all the associated objects in a background job.
1374
+ # * <tt>:destroy_async</tt> destroys all the associated objects in a background job. <b>WARNING:</b> Do not use
1375
+ # this option if the association is backed by foreign key constraints in your database. The foreign key
1376
+ # constraint actions will occur inside the same transaction that deletes its owner.
1375
1377
  # * <tt>:delete_all</tt> causes all the associated objects to be deleted directly from the database (so callbacks will not be executed).
1376
1378
  # * <tt>:nullify</tt> causes the foreign keys to be set to +NULL+. Polymorphic type will also be nullified
1377
1379
  # on polymorphic associations. Callbacks are not executed.
@@ -1523,7 +1525,9 @@ module ActiveRecord
1523
1525
  #
1524
1526
  # * <tt>nil</tt> do nothing (default).
1525
1527
  # * <tt>:destroy</tt> causes the associated object to also be destroyed
1526
- # * <tt>:destroy_async</tt> causes all the associated object to be destroyed in a background job.
1528
+ # * <tt>:destroy_async</tt> causes the associated object to be destroyed in a background job. <b>WARNING:</b> Do not use
1529
+ # this option if the association is backed by foreign key constraints in your database. The foreign key
1530
+ # constraint actions will occur inside the same transaction that deletes its owner.
1527
1531
  # * <tt>:delete</tt> causes the associated object to be deleted directly from the database (so callbacks will not execute)
1528
1532
  # * <tt>:nullify</tt> causes the foreign key to be set to +NULL+. Polymorphic type column is also nullified
1529
1533
  # on polymorphic associations. Callbacks are not executed.
@@ -173,7 +173,7 @@ module ActiveRecord
173
173
  # class Money < Struct.new(:amount, :currency)
174
174
  # end
175
175
  #
176
- # class MoneyType < Type::Value
176
+ # class MoneyType < ActiveRecord::Type::Value
177
177
  # def initialize(currency_converter:)
178
178
  # @currency_converter = currency_converter
179
179
  # end
@@ -24,7 +24,7 @@ module ActiveRecord
24
24
 
25
25
  attr_accessor :schema_cache
26
26
 
27
- def owner_name
27
+ def connection_klass
28
28
  nil
29
29
  end
30
30
  end
@@ -360,7 +360,7 @@ module ActiveRecord
360
360
  include ConnectionAdapters::AbstractPool
361
361
 
362
362
  attr_accessor :automatic_reconnect, :checkout_timeout
363
- attr_reader :db_config, :size, :reaper, :pool_config, :owner_name
363
+ attr_reader :db_config, :size, :reaper, :pool_config, :connection_klass
364
364
 
365
365
  delegate :schema_cache, :schema_cache=, to: :pool_config
366
366
 
@@ -375,7 +375,7 @@ module ActiveRecord
375
375
 
376
376
  @pool_config = pool_config
377
377
  @db_config = pool_config.db_config
378
- @owner_name = pool_config.connection_specification_name
378
+ @connection_klass = pool_config.connection_klass
379
379
 
380
380
  @checkout_timeout = db_config.checkout_timeout
381
381
  @idle_timeout = db_config.idle_timeout
@@ -1040,7 +1040,7 @@ module ActiveRecord
1040
1040
  end
1041
1041
  alias :connection_pools :connection_pool_list
1042
1042
 
1043
- def establish_connection(config, owner_name: Base.name, role: ActiveRecord::Base.current_role, shard: Base.current_shard)
1043
+ def establish_connection(config, owner_name: Base, role: ActiveRecord::Base.current_role, shard: Base.current_shard)
1044
1044
  owner_name = config.to_s if config.is_a?(Symbol)
1045
1045
 
1046
1046
  pool_config = resolve_pool_config(config, owner_name)
@@ -395,7 +395,7 @@ module ActiveRecord
395
395
 
396
396
  # Inserts the given fixture into the table. Overridden in adapters that require
397
397
  # something beyond a simple insert (e.g. Oracle).
398
- # Most of adapters should implement `insert_fixtures_set` that leverages bulk SQL insert.
398
+ # Most of adapters should implement +insert_fixtures_set+ that leverages bulk SQL insert.
399
399
  # We keep this method to provide fallback
400
400
  # for databases like sqlite that do not support bulk inserts.
401
401
  def insert_fixture(fixture, table_name)
@@ -7,7 +7,7 @@ module ActiveRecord
7
7
  module QueryCache
8
8
  class << self
9
9
  def included(base) #:nodoc:
10
- dirties_query_cache base, :insert, :update, :delete, :truncate, :truncate_tables,
10
+ dirties_query_cache base, :create, :insert, :update, :delete, :truncate, :truncate_tables,
11
11
  :rollback_to_savepoint, :rollback_db_transaction, :exec_insert_all
12
12
 
13
13
  base.set_callback :checkout, :after, :configure_query_cache!
@@ -71,6 +71,10 @@ module ActiveRecord
71
71
  end
72
72
  CODE
73
73
  end
74
+
75
+ def aliased_types(name, fallback)
76
+ "timestamp" == name ? :datetime : fallback
77
+ end
74
78
  end
75
79
 
76
80
  AddColumnDefinition = Struct.new(:column) # :nodoc:
@@ -1387,8 +1387,14 @@ module ActiveRecord
1387
1387
 
1388
1388
  checks = []
1389
1389
 
1390
+ if !options.key?(:name) && column_name.is_a?(String) && /\W/.match?(column_name)
1391
+ options[:name] = index_name(table_name, column_name)
1392
+ column_names = []
1393
+ else
1394
+ column_names = index_column_names(column_name || options[:column])
1395
+ end
1396
+
1390
1397
  checks << lambda { |i| i.name == options[:name].to_s } if options.key?(:name)
1391
- column_names = index_column_names(column_name || options[:column])
1392
1398
 
1393
1399
  if column_names.present?
1394
1400
  checks << lambda { |i| index_name(table_name, i.columns) == index_name(table_name, column_names) }
@@ -111,22 +111,21 @@ module ActiveRecord
111
111
  @config.fetch(:use_metadata_table, true)
112
112
  end
113
113
 
114
- # Determines whether writes are currently being prevents.
114
+ # Determines whether writes are currently being prevented.
115
115
  #
116
116
  # Returns true if the connection is a replica.
117
117
  #
118
118
  # If the application is using legacy handling, returns
119
- # true if `connection_handler.prevent_writes` is set.
119
+ # true if +connection_handler.prevent_writes+ is set.
120
120
  #
121
121
  # If the application is using the new connection handling
122
- # will return true based on `current_preventing_writes`.
122
+ # will return true based on +current_preventing_writes+.
123
123
  def preventing_writes?
124
124
  return true if replica?
125
125
  return ActiveRecord::Base.connection_handler.prevent_writes if ActiveRecord::Base.legacy_connection_handling
126
- return false if owner_name.nil?
126
+ return false if connection_klass.nil?
127
127
 
128
- klass = self.owner_name.safe_constantize
129
- klass&.current_preventing_writes
128
+ connection_klass.current_preventing_writes
130
129
  end
131
130
 
132
131
  def migrations_paths # :nodoc:
@@ -202,8 +201,8 @@ module ActiveRecord
202
201
  @owner = Thread.current
203
202
  end
204
203
 
205
- def owner_name # :nodoc:
206
- @pool.owner_name
204
+ def connection_klass # :nodoc:
205
+ @pool.connection_klass
207
206
  end
208
207
 
209
208
  def schema_cache