activerecord 6.1.3.2 → 7.0.0.alpha2

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 (229) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +734 -1058
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/active_record/aggregations.rb +1 -1
  6. data/lib/active_record/association_relation.rb +0 -10
  7. data/lib/active_record/associations/association.rb +35 -7
  8. data/lib/active_record/associations/association_scope.rb +1 -3
  9. data/lib/active_record/associations/belongs_to_association.rb +16 -6
  10. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
  11. data/lib/active_record/associations/builder/association.rb +8 -2
  12. data/lib/active_record/associations/builder/belongs_to.rb +19 -6
  13. data/lib/active_record/associations/builder/collection_association.rb +1 -1
  14. data/lib/active_record/associations/builder/has_many.rb +3 -2
  15. data/lib/active_record/associations/builder/has_one.rb +2 -1
  16. data/lib/active_record/associations/builder/singular_association.rb +2 -2
  17. data/lib/active_record/associations/collection_association.rb +24 -25
  18. data/lib/active_record/associations/collection_proxy.rb +8 -3
  19. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  20. data/lib/active_record/associations/has_many_association.rb +1 -1
  21. data/lib/active_record/associations/has_many_through_association.rb +2 -1
  22. data/lib/active_record/associations/has_one_association.rb +10 -7
  23. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  24. data/lib/active_record/associations/preloader/association.rb +161 -49
  25. data/lib/active_record/associations/preloader/batch.rb +51 -0
  26. data/lib/active_record/associations/preloader/branch.rb +147 -0
  27. data/lib/active_record/associations/preloader/through_association.rb +37 -11
  28. data/lib/active_record/associations/preloader.rb +46 -110
  29. data/lib/active_record/associations/singular_association.rb +8 -2
  30. data/lib/active_record/associations/through_association.rb +1 -1
  31. data/lib/active_record/associations.rb +76 -81
  32. data/lib/active_record/asynchronous_queries_tracker.rb +57 -0
  33. data/lib/active_record/attribute_assignment.rb +1 -1
  34. data/lib/active_record/attribute_methods/before_type_cast.rb +7 -2
  35. data/lib/active_record/attribute_methods/dirty.rb +41 -16
  36. data/lib/active_record/attribute_methods/primary_key.rb +2 -2
  37. data/lib/active_record/attribute_methods/query.rb +2 -2
  38. data/lib/active_record/attribute_methods/read.rb +7 -5
  39. data/lib/active_record/attribute_methods/serialization.rb +66 -12
  40. data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -3
  41. data/lib/active_record/attribute_methods/write.rb +7 -10
  42. data/lib/active_record/attribute_methods.rb +6 -9
  43. data/lib/active_record/attributes.rb +24 -35
  44. data/lib/active_record/autosave_association.rb +3 -18
  45. data/lib/active_record/base.rb +19 -1
  46. data/lib/active_record/callbacks.rb +2 -2
  47. data/lib/active_record/coders/yaml_column.rb +11 -1
  48. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +312 -0
  49. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
  50. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +31 -558
  52. data/lib/active_record/connection_adapters/abstract/database_statements.rb +45 -21
  53. data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -12
  54. data/lib/active_record/connection_adapters/abstract/quoting.rb +14 -7
  55. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +5 -18
  56. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -9
  57. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +60 -16
  58. data/lib/active_record/connection_adapters/abstract/transaction.rb +17 -6
  59. data/lib/active_record/connection_adapters/abstract_adapter.rb +115 -69
  60. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +96 -81
  61. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +6 -2
  62. data/lib/active_record/connection_adapters/mysql/database_statements.rb +33 -21
  63. data/lib/active_record/connection_adapters/mysql/quoting.rb +16 -1
  64. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +3 -0
  65. data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -6
  66. data/lib/active_record/connection_adapters/pool_config.rb +1 -3
  67. data/lib/active_record/connection_adapters/pool_manager.rb +5 -1
  68. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +19 -12
  69. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
  70. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
  71. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
  72. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
  73. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  74. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +28 -0
  75. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
  76. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  77. data/lib/active_record/connection_adapters/postgresql/quoting.rb +6 -6
  78. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +32 -0
  79. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +5 -1
  80. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +12 -12
  81. data/lib/active_record/connection_adapters/postgresql_adapter.rb +157 -100
  82. data/lib/active_record/connection_adapters/schema_cache.rb +35 -4
  83. data/lib/active_record/connection_adapters/sql_type_metadata.rb +0 -2
  84. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +23 -17
  85. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +4 -2
  86. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -30
  87. data/lib/active_record/connection_adapters.rb +8 -5
  88. data/lib/active_record/connection_handling.rb +20 -38
  89. data/lib/active_record/core.rb +129 -117
  90. data/lib/active_record/database_configurations/database_config.rb +12 -0
  91. data/lib/active_record/database_configurations/hash_config.rb +27 -1
  92. data/lib/active_record/database_configurations/url_config.rb +2 -2
  93. data/lib/active_record/database_configurations.rb +18 -9
  94. data/lib/active_record/delegated_type.rb +33 -11
  95. data/lib/active_record/destroy_association_async_job.rb +1 -1
  96. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  97. data/lib/active_record/dynamic_matchers.rb +1 -1
  98. data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
  99. data/lib/active_record/encryption/cipher.rb +53 -0
  100. data/lib/active_record/encryption/config.rb +44 -0
  101. data/lib/active_record/encryption/configurable.rb +61 -0
  102. data/lib/active_record/encryption/context.rb +35 -0
  103. data/lib/active_record/encryption/contexts.rb +72 -0
  104. data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
  105. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  106. data/lib/active_record/encryption/encryptable_record.rb +208 -0
  107. data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -0
  108. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  109. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  110. data/lib/active_record/encryption/encryptor.rb +155 -0
  111. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  112. data/lib/active_record/encryption/errors.rb +15 -0
  113. data/lib/active_record/encryption/extended_deterministic_queries.rb +160 -0
  114. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +29 -0
  115. data/lib/active_record/encryption/key.rb +28 -0
  116. data/lib/active_record/encryption/key_generator.rb +42 -0
  117. data/lib/active_record/encryption/key_provider.rb +46 -0
  118. data/lib/active_record/encryption/message.rb +33 -0
  119. data/lib/active_record/encryption/message_serializer.rb +80 -0
  120. data/lib/active_record/encryption/null_encryptor.rb +21 -0
  121. data/lib/active_record/encryption/properties.rb +76 -0
  122. data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
  123. data/lib/active_record/encryption/scheme.rb +99 -0
  124. data/lib/active_record/encryption.rb +55 -0
  125. data/lib/active_record/enum.rb +44 -46
  126. data/lib/active_record/errors.rb +66 -3
  127. data/lib/active_record/fixture_set/file.rb +15 -1
  128. data/lib/active_record/fixture_set/table_row.rb +40 -5
  129. data/lib/active_record/fixture_set/table_rows.rb +4 -4
  130. data/lib/active_record/fixtures.rb +16 -11
  131. data/lib/active_record/future_result.rb +139 -0
  132. data/lib/active_record/gem_version.rb +4 -4
  133. data/lib/active_record/inheritance.rb +55 -17
  134. data/lib/active_record/insert_all.rb +39 -6
  135. data/lib/active_record/integration.rb +1 -1
  136. data/lib/active_record/internal_metadata.rb +3 -5
  137. data/lib/active_record/legacy_yaml_adapter.rb +1 -1
  138. data/lib/active_record/locking/optimistic.rb +10 -9
  139. data/lib/active_record/log_subscriber.rb +6 -2
  140. data/lib/active_record/middleware/database_selector/resolver.rb +6 -10
  141. data/lib/active_record/middleware/database_selector.rb +8 -3
  142. data/lib/active_record/migration/command_recorder.rb +4 -4
  143. data/lib/active_record/migration/compatibility.rb +83 -1
  144. data/lib/active_record/migration/join_table.rb +1 -1
  145. data/lib/active_record/migration.rb +109 -79
  146. data/lib/active_record/model_schema.rb +46 -32
  147. data/lib/active_record/nested_attributes.rb +3 -3
  148. data/lib/active_record/no_touching.rb +2 -2
  149. data/lib/active_record/null_relation.rb +2 -6
  150. data/lib/active_record/persistence.rb +134 -45
  151. data/lib/active_record/query_cache.rb +2 -2
  152. data/lib/active_record/query_logs.rb +203 -0
  153. data/lib/active_record/querying.rb +15 -5
  154. data/lib/active_record/railtie.rb +117 -17
  155. data/lib/active_record/railties/controller_runtime.rb +1 -1
  156. data/lib/active_record/railties/databases.rake +83 -58
  157. data/lib/active_record/readonly_attributes.rb +11 -0
  158. data/lib/active_record/reflection.rb +45 -44
  159. data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
  160. data/lib/active_record/relation/batches.rb +3 -3
  161. data/lib/active_record/relation/calculations.rb +42 -25
  162. data/lib/active_record/relation/delegation.rb +6 -6
  163. data/lib/active_record/relation/finder_methods.rb +32 -23
  164. data/lib/active_record/relation/merger.rb +20 -13
  165. data/lib/active_record/relation/predicate_builder.rb +1 -6
  166. data/lib/active_record/relation/query_attribute.rb +5 -11
  167. data/lib/active_record/relation/query_methods.rb +233 -50
  168. data/lib/active_record/relation/record_fetch_warning.rb +2 -2
  169. data/lib/active_record/relation/spawn_methods.rb +2 -2
  170. data/lib/active_record/relation/where_clause.rb +22 -15
  171. data/lib/active_record/relation.rb +170 -87
  172. data/lib/active_record/result.rb +17 -2
  173. data/lib/active_record/runtime_registry.rb +2 -4
  174. data/lib/active_record/sanitization.rb +11 -7
  175. data/lib/active_record/schema_dumper.rb +3 -3
  176. data/lib/active_record/schema_migration.rb +0 -4
  177. data/lib/active_record/scoping/default.rb +62 -15
  178. data/lib/active_record/scoping/named.rb +3 -11
  179. data/lib/active_record/scoping.rb +40 -22
  180. data/lib/active_record/serialization.rb +1 -1
  181. data/lib/active_record/signed_id.rb +1 -1
  182. data/lib/active_record/statement_cache.rb +2 -2
  183. data/lib/active_record/tasks/database_tasks.rb +107 -23
  184. data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
  185. data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -11
  186. data/lib/active_record/test_databases.rb +1 -1
  187. data/lib/active_record/test_fixtures.rb +45 -4
  188. data/lib/active_record/timestamp.rb +3 -4
  189. data/lib/active_record/transactions.rb +9 -14
  190. data/lib/active_record/translation.rb +2 -2
  191. data/lib/active_record/type/adapter_specific_registry.rb +32 -7
  192. data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
  193. data/lib/active_record/type/internal/timezone.rb +2 -2
  194. data/lib/active_record/type/serialized.rb +1 -1
  195. data/lib/active_record/type/type_map.rb +17 -20
  196. data/lib/active_record/type.rb +1 -2
  197. data/lib/active_record/validations/associated.rb +1 -1
  198. data/lib/active_record/validations/numericality.rb +1 -1
  199. data/lib/active_record.rb +170 -2
  200. data/lib/arel/attributes/attribute.rb +0 -8
  201. data/lib/arel/collectors/bind.rb +2 -2
  202. data/lib/arel/collectors/composite.rb +3 -3
  203. data/lib/arel/collectors/sql_string.rb +1 -1
  204. data/lib/arel/collectors/substitute_binds.rb +1 -1
  205. data/lib/arel/crud.rb +18 -22
  206. data/lib/arel/delete_manager.rb +2 -4
  207. data/lib/arel/insert_manager.rb +2 -3
  208. data/lib/arel/nodes/casted.rb +1 -1
  209. data/lib/arel/nodes/delete_statement.rb +8 -13
  210. data/lib/arel/nodes/homogeneous_in.rb +4 -0
  211. data/lib/arel/nodes/insert_statement.rb +2 -2
  212. data/lib/arel/nodes/select_core.rb +2 -2
  213. data/lib/arel/nodes/select_statement.rb +2 -2
  214. data/lib/arel/nodes/update_statement.rb +3 -2
  215. data/lib/arel/predications.rb +3 -3
  216. data/lib/arel/select_manager.rb +10 -4
  217. data/lib/arel/table.rb +0 -1
  218. data/lib/arel/tree_manager.rb +0 -12
  219. data/lib/arel/update_manager.rb +2 -4
  220. data/lib/arel/visitors/dot.rb +80 -90
  221. data/lib/arel/visitors/mysql.rb +6 -1
  222. data/lib/arel/visitors/postgresql.rb +0 -10
  223. data/lib/arel/visitors/to_sql.rb +44 -3
  224. data/lib/arel.rb +1 -1
  225. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  226. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
  227. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  228. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  229. metadata +55 -16
@@ -5,7 +5,7 @@ require "active_record/log_subscriber"
5
5
 
6
6
  module ActiveRecord
7
7
  module Railties # :nodoc:
8
- module ControllerRuntime #:nodoc:
8
+ module ControllerRuntime # :nodoc:
9
9
  extend ActiveSupport::Concern
10
10
 
11
11
  module ClassMethods # :nodoc:
@@ -86,19 +86,30 @@ db_namespace = namespace :db do
86
86
 
87
87
  desc "Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)."
88
88
  task migrate: :load_config do
89
- original_db_config = ActiveRecord::Base.connection_db_config
90
- ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
91
- ActiveRecord::Base.establish_connection(db_config)
89
+ db_configs = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env)
90
+
91
+ if db_configs.size == 1
92
92
  ActiveRecord::Tasks::DatabaseTasks.migrate
93
+ else
94
+ original_db_config = ActiveRecord::Base.connection_db_config
95
+ mapped_versions = ActiveRecord::Tasks::DatabaseTasks.db_configs_with_versions(db_configs)
96
+
97
+ mapped_versions.sort.each do |version, db_configs|
98
+ db_configs.each do |db_config|
99
+ ActiveRecord::Base.establish_connection(db_config)
100
+ ActiveRecord::Tasks::DatabaseTasks.migrate(version)
101
+ end
102
+ end
93
103
  end
104
+
94
105
  db_namespace["_dump"].invoke
95
106
  ensure
96
- ActiveRecord::Base.establish_connection(original_db_config)
107
+ ActiveRecord::Base.establish_connection(original_db_config) if original_db_config
97
108
  end
98
109
 
99
- # IMPORTANT: This task won't dump the schema if ActiveRecord::Base.dump_schema_after_migration is set to false
110
+ # IMPORTANT: This task won't dump the schema if ActiveRecord.dump_schema_after_migration is set to false
100
111
  task :_dump do
101
- if ActiveRecord::Base.dump_schema_after_migration
112
+ if ActiveRecord.dump_schema_after_migration
102
113
  db_namespace["schema:dump"].invoke
103
114
  end
104
115
  # Allow this task to be called as many times as required. An example is the
@@ -108,11 +119,15 @@ db_namespace = namespace :db do
108
119
 
109
120
  namespace :_dump do
110
121
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
111
- # IMPORTANT: This task won't dump the schema if ActiveRecord::Base.dump_schema_after_migration is set to false
122
+ # IMPORTANT: This task won't dump the schema if ActiveRecord.dump_schema_after_migration is set to false
112
123
  task name do
113
- if ActiveRecord::Base.dump_schema_after_migration
124
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, name: name)
125
+
126
+ if ActiveRecord.dump_schema_after_migration && db_config.schema_dump
127
+ ActiveRecord::Base.establish_connection(db_config)
114
128
  db_namespace["schema:dump:#{name}"].invoke
115
129
  end
130
+
116
131
  # Allow this task to be called as many times as required. An example is the
117
132
  # migrate:redo task, which calls other two internally that depend on this one.
118
133
  db_namespace["_dump:#{name}"].reenable
@@ -275,6 +290,7 @@ db_namespace = namespace :db do
275
290
  desc "Rolls the schema back to the previous version (specify steps w/ STEP=n)."
276
291
  task rollback: :load_config do
277
292
  ActiveRecord::Tasks::DatabaseTasks.raise_for_multi_db(command: "db:rollback")
293
+ raise "VERSION is not supported - To rollback a specific version, use db:migrate:down" if ENV["VERSION"]
278
294
 
279
295
  step = ENV["STEP"] ? ENV["STEP"].to_i : 1
280
296
 
@@ -290,7 +306,16 @@ db_namespace = namespace :db do
290
306
  db_namespace["_dump"].invoke
291
307
  end
292
308
 
293
- desc "Drops and recreates the database from db/schema.rb for the current environment and loads the seeds."
309
+ namespace :reset do
310
+ task all: ["db:drop", "db:setup"]
311
+
312
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
313
+ desc "Drops and recreates the #{name} database from its schema for the current environment and loads the seeds."
314
+ task name => ["db:drop:#{name}", "db:setup:#{name}"]
315
+ end
316
+ end
317
+
318
+ desc "Drops and recreates all databases from their schema for the current environment and loads the seeds."
294
319
  task reset: [ "db:drop", "db:setup" ]
295
320
 
296
321
  # desc "Retrieves the charset for the current environment's database"
@@ -349,41 +374,21 @@ db_namespace = namespace :db do
349
374
  end
350
375
  end
351
376
 
352
- desc "Creates the database, loads the schema, and initializes with the seed data (use db:reset to also drop the database first)"
377
+ namespace :setup do
378
+ task all: ["db:create", :environment, "db:schema:load", :seed]
379
+
380
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
381
+ desc "Creates the #{name} database, loads the schema, and initializes with the seed data (use db:reset:#{name} to also drop the database first)"
382
+ task name => ["db:create:#{name}", :environment, "db:schema:load:#{name}", "db:seed"]
383
+ end
384
+ end
385
+
386
+ desc "Creates all databases, loads all schemas, and initializes with the seed data (use db:reset to also drop all databases first)"
353
387
  task setup: ["db:create", :environment, "db:schema:load", :seed]
354
388
 
355
389
  desc "Runs setup if database does not exist, or runs migrations if it does"
356
390
  task prepare: :load_config do
357
- seed = false
358
-
359
- ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
360
- ActiveRecord::Base.establish_connection(db_config)
361
-
362
- # Skipped when no database
363
- ActiveRecord::Tasks::DatabaseTasks.migrate
364
-
365
- if ActiveRecord::Base.dump_schema_after_migration
366
- ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, ActiveRecord::Base.schema_format)
367
- end
368
- rescue ActiveRecord::NoDatabaseError
369
- config_name = db_config.name
370
- ActiveRecord::Tasks::DatabaseTasks.create_current(db_config.env_name, config_name)
371
-
372
- if File.exist?(ActiveRecord::Tasks::DatabaseTasks.dump_filename(config_name))
373
- ActiveRecord::Tasks::DatabaseTasks.load_schema(
374
- db_config,
375
- ActiveRecord::Base.schema_format,
376
- nil
377
- )
378
- else
379
- ActiveRecord::Tasks::DatabaseTasks.migrate
380
- end
381
-
382
- seed = true
383
- end
384
-
385
- ActiveRecord::Base.establish_connection
386
- ActiveRecord::Tasks::DatabaseTasks.load_seed if seed
391
+ ActiveRecord::Tasks::DatabaseTasks.prepare_all
387
392
  end
388
393
 
389
394
  desc "Loads the seed data from db/seeds.rb"
@@ -413,8 +418,9 @@ db_namespace = namespace :db do
413
418
  fixture_files = if ENV["FIXTURES"]
414
419
  ENV["FIXTURES"].split(",")
415
420
  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] }
421
+ files = Dir[File.join(fixtures_dir, "**/*.{yml}")]
422
+ files.reject! { |f| f.start_with?(File.join(fixtures_dir, "files")) }
423
+ files.map! { |f| f[fixtures_dir.to_s.size..-5].delete_prefix("/") }
418
424
  end
419
425
 
420
426
  ActiveRecord::FixtureSet.create_fixtures(fixtures_dir, fixture_files)
@@ -449,8 +455,10 @@ db_namespace = namespace :db do
449
455
  desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`)"
450
456
  task dump: :load_config do
451
457
  ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
452
- ActiveRecord::Base.establish_connection(db_config)
453
- ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config)
458
+ if db_config.schema_dump
459
+ ActiveRecord::Base.establish_connection(db_config)
460
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config)
461
+ end
454
462
  end
455
463
 
456
464
  db_namespace["schema:dump"].reenable
@@ -458,15 +466,15 @@ db_namespace = namespace :db do
458
466
 
459
467
  desc "Loads a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) into the database"
460
468
  task load: [:load_config, :check_protected_environments] do
461
- ActiveRecord::Tasks::DatabaseTasks.load_schema_current(ActiveRecord::Base.schema_format, ENV["SCHEMA"])
469
+ ActiveRecord::Tasks::DatabaseTasks.load_schema_current(ActiveRecord.schema_format, ENV["SCHEMA"])
462
470
  end
463
471
 
464
472
  task load_if_ruby: ["db:create", :environment] do
465
473
  ActiveSupport::Deprecation.warn(<<-MSG.squish)
466
- Using `bin/rails db:schema:load_if_ruby` is deprecated and will be removed in Rails 6.2.
474
+ Using `bin/rails db:schema:load_if_ruby` is deprecated and will be removed in Rails 7.0.
467
475
  Configure the format using `config.active_record.schema_format = :ruby` to use `schema.rb` and run `bin/rails db:schema:load` instead.
468
476
  MSG
469
- db_namespace["schema:load"].invoke if ActiveRecord::Base.schema_format == :ruby
477
+ db_namespace["schema:load"].invoke if ActiveRecord.schema_format == :ruby
470
478
  end
471
479
 
472
480
  namespace :dump do
@@ -485,8 +493,11 @@ db_namespace = namespace :db do
485
493
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
486
494
  desc "Loads a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) into the #{name} database"
487
495
  task name => :load_config do
496
+ original_db_config = ActiveRecord::Base.connection_db_config
488
497
  db_config = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, name: name)
489
- ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ActiveRecord::Base.schema_format, ENV["SCHEMA"])
498
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ActiveRecord.schema_format, ENV["SCHEMA"])
499
+ ensure
500
+ ActiveRecord::Base.establish_connection(original_db_config) if original_db_config
490
501
  end
491
502
  end
492
503
  end
@@ -526,7 +537,7 @@ db_namespace = namespace :db do
526
537
  desc "Dumps the database structure to db/structure.sql. Specify another file with SCHEMA=db/my_structure.sql"
527
538
  task dump: :load_config do
528
539
  ActiveSupport::Deprecation.warn(<<-MSG.squish)
529
- Using `bin/rails db:structure:dump` is deprecated and will be removed in Rails 6.2.
540
+ Using `bin/rails db:structure:dump` is deprecated and will be removed in Rails 7.0.
530
541
  Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:dump` instead.
531
542
  MSG
532
543
 
@@ -537,7 +548,7 @@ db_namespace = namespace :db do
537
548
  desc "Recreates the databases from the structure.sql file"
538
549
  task load: [:load_config, :check_protected_environments] do
539
550
  ActiveSupport::Deprecation.warn(<<-MSG.squish)
540
- Using `bin/rails db:structure:load` is deprecated and will be removed in Rails 6.2.
551
+ Using `bin/rails db:structure:load` is deprecated and will be removed in Rails 7.0.
541
552
  Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:load` instead.
542
553
  MSG
543
554
  db_namespace["schema:load"].invoke
@@ -545,10 +556,10 @@ db_namespace = namespace :db do
545
556
 
546
557
  task load_if_sql: ["db:create", :environment] do
547
558
  ActiveSupport::Deprecation.warn(<<-MSG.squish)
548
- Using `bin/rails db:structure:load_if_sql` is deprecated and will be removed in Rails 6.2.
559
+ Using `bin/rails db:structure:load_if_sql` is deprecated and will be removed in Rails 7.0.
549
560
  Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:load` instead.
550
561
  MSG
551
- db_namespace["schema:load"].invoke if ActiveRecord::Base.schema_format == :sql
562
+ db_namespace["schema:load"].invoke if ActiveRecord.schema_format == :sql
552
563
  end
553
564
 
554
565
  namespace :dump do
@@ -556,7 +567,7 @@ db_namespace = namespace :db do
556
567
  desc "Dumps the #{name} database structure to db/structure.sql. Specify another file with SCHEMA=db/my_structure.sql"
557
568
  task name => :load_config do
558
569
  ActiveSupport::Deprecation.warn(<<-MSG.squish)
559
- Using `bin/rails db:structure:dump:#{name}` is deprecated and will be removed in Rails 6.2.
570
+ Using `bin/rails db:structure:dump:#{name}` is deprecated and will be removed in Rails 7.0.
560
571
  Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:dump:#{name}` instead.
561
572
  MSG
562
573
  db_namespace["schema:dump:#{name}"].invoke
@@ -570,7 +581,7 @@ db_namespace = namespace :db do
570
581
  desc "Recreates the #{name} database from the structure.sql file"
571
582
  task name => :load_config do
572
583
  ActiveSupport::Deprecation.warn(<<-MSG.squish)
573
- Using `bin/rails db:structure:load:#{name}` is deprecated and will be removed in Rails 6.2.
584
+ Using `bin/rails db:structure:load:#{name}` is deprecated and will be removed in Rails 7.0.
574
585
  Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:load:#{name}` instead.
575
586
  MSG
576
587
  db_namespace["schema:load:#{name}"].invoke
@@ -579,6 +590,20 @@ db_namespace = namespace :db do
579
590
  end
580
591
  end
581
592
 
593
+ namespace :encryption do
594
+ desc "Generate a set of keys for configuring Active Record encryption in a given environment"
595
+ task :init do
596
+ puts <<~MSG
597
+ Add this entry to the credentials of the target environment:#{' '}
598
+
599
+ active_record_encryption:
600
+ primary_key: #{SecureRandom.alphanumeric(32)}
601
+ deterministic_key: #{SecureRandom.alphanumeric(32)}
602
+ key_derivation_salt: #{SecureRandom.alphanumeric(32)}
603
+ MSG
604
+ end
605
+ end
606
+
582
607
  namespace :test do
583
608
  # desc "Recreate the test database from the current schema"
584
609
  task load: %w(db:test:purge) do
@@ -591,7 +616,7 @@ db_namespace = namespace :db do
591
616
  ActiveRecord::Schema.verbose = false
592
617
  ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
593
618
  filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(db_config.name)
594
- ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ActiveRecord::Base.schema_format, filename)
619
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ActiveRecord.schema_format, filename)
595
620
  end
596
621
  ensure
597
622
  if should_reconnect
@@ -602,7 +627,7 @@ db_namespace = namespace :db do
602
627
  # desc "Recreate the test database from an existent structure.sql file"
603
628
  task load_structure: %w(db:test:purge) do
604
629
  ActiveSupport::Deprecation.warn(<<-MSG.squish)
605
- Using `bin/rails db:test:load_structure` is deprecated and will be removed in Rails 6.2.
630
+ Using `bin/rails db:test:load_structure` is deprecated and will be removed in Rails 7.0.
606
631
  Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:test:load_schema` instead.
607
632
  MSG
608
633
  db_namespace["test:load_schema"].invoke
@@ -637,7 +662,7 @@ db_namespace = namespace :db do
637
662
  ActiveRecord::Schema.verbose = false
638
663
  filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(name)
639
664
  db_config = ActiveRecord::Base.configurations.configs_for(env_name: "test", name: name)
640
- ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ActiveRecord::Base.schema_format, filename)
665
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ActiveRecord.schema_format, filename)
641
666
  ensure
642
667
  if should_reconnect
643
668
  ActiveRecord::Base.establish_connection(ActiveRecord::Tasks::DatabaseTasks.env.to_sym)
@@ -649,7 +674,7 @@ db_namespace = namespace :db do
649
674
  namespace :load_structure do
650
675
  task name => "db:test:purge:#{name}" do
651
676
  ActiveSupport::Deprecation.warn(<<-MSG.squish)
652
- Using `bin/rails db:test:load_structure:#{name}` is deprecated and will be removed in Rails 6.2.
677
+ Using `bin/rails db:test:load_structure:#{name}` is deprecated and will be removed in Rails 7.0.
653
678
  Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:test:load_structure:#{name}` instead.
654
679
  MSG
655
680
  db_namespace["test:load_schema:#{name}"].invoke
@@ -11,6 +11,17 @@ module ActiveRecord
11
11
  module ClassMethods
12
12
  # Attributes listed as readonly will be used to create a new record but update operations will
13
13
  # ignore these fields.
14
+ #
15
+ # You can assign a new value to a readonly attribute, but it will be ignored when the record is updated.
16
+ #
17
+ # ==== Examples
18
+ #
19
+ # class Post < ActiveRecord::Base
20
+ # attr_readonly :title
21
+ # end
22
+ #
23
+ # post = Post.create!(title: "Introducing Ruby on Rails!")
24
+ # post.update(title: "a different title") # change to title will be ignored
14
25
  def attr_readonly(*attributes)
15
26
  self._attr_readonly = Set.new(attributes.map(&:to_s)) + (_attr_readonly || [])
16
27
  end
@@ -115,7 +115,7 @@ module ActiveRecord
115
115
  reflections[association.to_s]
116
116
  end
117
117
 
118
- def _reflect_on_association(association) #:nodoc:
118
+ def _reflect_on_association(association) # :nodoc:
119
119
  _reflections[association.to_s]
120
120
  end
121
121
 
@@ -194,9 +194,9 @@ module ActiveRecord
194
194
  klass_scope
195
195
  end
196
196
 
197
- def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
197
+ def join_scopes(table, predicate_builder, klass = self.klass, record = nil) # :nodoc:
198
198
  if scope
199
- [scope_for(build_scope(table, predicate_builder, klass))]
199
+ [scope_for(build_scope(table, predicate_builder, klass), record)]
200
200
  else
201
201
  []
202
202
  end
@@ -237,7 +237,7 @@ module ActiveRecord
237
237
  end
238
238
  end
239
239
 
240
- # This shit is nasty. We need to avoid the following situation:
240
+ # We need to avoid the following situation:
241
241
  #
242
242
  # * An associated record is deleted via record.destroy
243
243
  # * Hence the callbacks run, and they find a belongs_to on the record with a
@@ -306,6 +306,12 @@ module ActiveRecord
306
306
  def primary_key(klass)
307
307
  klass.primary_key || raise(UnknownPrimaryKey.new(klass))
308
308
  end
309
+
310
+ def ensure_option_not_given_as_class!(option_name)
311
+ if options[option_name] && options[option_name].class == Class
312
+ raise ArgumentError, "A class was passed to `:#{option_name}` but we are expecting a string."
313
+ end
314
+ end
309
315
  end
310
316
 
311
317
  # Base class for AggregateReflection and AssociationReflection. Objects of
@@ -392,7 +398,7 @@ module ActiveRecord
392
398
 
393
399
  # Holds all the metadata about an aggregation as it was specified in the
394
400
  # Active Record class.
395
- class AggregateReflection < MacroReflection #:nodoc:
401
+ class AggregateReflection < MacroReflection # :nodoc:
396
402
  def mapping
397
403
  mapping = options[:mapping] || [name, name]
398
404
  mapping.first.is_a?(Array) ? mapping : [mapping]
@@ -401,12 +407,29 @@ module ActiveRecord
401
407
 
402
408
  # Holds all the metadata about an association as it was specified in the
403
409
  # Active Record class.
404
- class AssociationReflection < MacroReflection #:nodoc:
410
+ class AssociationReflection < MacroReflection # :nodoc:
405
411
  def compute_class(name)
406
412
  if polymorphic?
407
413
  raise ArgumentError, "Polymorphic associations do not support computing the class."
408
414
  end
409
- active_record.send(:compute_type, name)
415
+
416
+ msg = <<-MSG.squish
417
+ Rails couldn't find a valid model for #{name} association.
418
+ Please provide the :class_name option on the association declaration.
419
+ If :class_name is already provided, make sure it's an ActiveRecord::Base subclass.
420
+ MSG
421
+
422
+ begin
423
+ klass = active_record.send(:compute_type, name)
424
+
425
+ unless klass < ActiveRecord::Base
426
+ raise ArgumentError, msg
427
+ end
428
+
429
+ klass
430
+ rescue NameError
431
+ raise NameError, msg
432
+ end
410
433
  end
411
434
 
412
435
  attr_reader :type, :foreign_type
@@ -416,11 +439,8 @@ module ActiveRecord
416
439
  super
417
440
  @type = -(options[:foreign_type]&.to_s || "#{options[:as]}_type") if options[:as]
418
441
  @foreign_type = -(options[:foreign_type]&.to_s || "#{name}_type") if options[:polymorphic]
419
- @constructable = calculate_constructable(macro, options)
420
442
 
421
- if options[:class_name] && options[:class_name].class == Class
422
- raise ArgumentError, "A class was passed to `:class_name` but we are expecting a string."
423
- end
443
+ ensure_option_not_given_as_class!(:class_name)
424
444
  end
425
445
 
426
446
  def association_scope_cache(klass, owner, &block)
@@ -431,10 +451,6 @@ module ActiveRecord
431
451
  klass.cached_find_by_statement(key, &block)
432
452
  end
433
453
 
434
- def constructable? # :nodoc:
435
- @constructable
436
- end
437
-
438
454
  def join_table
439
455
  @join_table ||= -(options[:join_table]&.to_s || derive_join_table)
440
456
  end
@@ -467,18 +483,17 @@ module ActiveRecord
467
483
  check_validity_of_inverse!
468
484
  end
469
485
 
470
- def check_preloadable!
486
+ def check_eager_loadable!
471
487
  return unless scope
472
488
 
473
489
  unless scope.arity == 0
474
490
  raise ArgumentError, <<-MSG.squish
475
491
  The association scope '#{name}' is instance dependent (the scope
476
- block takes an argument). Preloading instance dependent scopes is
477
- not supported.
492
+ block takes an argument). Eager loading instance dependent scopes
493
+ is not supported.
478
494
  MSG
479
495
  end
480
496
  end
481
- alias :check_eager_loadable! :check_preloadable!
482
497
 
483
498
  def join_id_for(owner) # :nodoc:
484
499
  owner[join_foreign_key]
@@ -563,9 +578,6 @@ module ActiveRecord
563
578
  options[:polymorphic]
564
579
  end
565
580
 
566
- VALID_AUTOMATIC_INVERSE_MACROS = [:has_many, :has_one, :belongs_to]
567
- INVALID_AUTOMATIC_INVERSE_OPTIONS = [:through, :foreign_key]
568
-
569
581
  def add_as_source(seed)
570
582
  seed
571
583
  end
@@ -583,10 +595,6 @@ module ActiveRecord
583
595
  end
584
596
 
585
597
  private
586
- def calculate_constructable(macro, options)
587
- true
588
- end
589
-
590
598
  # Attempts to find the inverse association name automatically.
591
599
  # If it cannot find a suitable inverse association name, it returns
592
600
  # +nil+.
@@ -639,8 +647,8 @@ module ActiveRecord
639
647
  # inverse, so we exclude reflections with scopes.
640
648
  def can_find_inverse_of_automatically?(reflection)
641
649
  reflection.options[:inverse_of] != false &&
642
- VALID_AUTOMATIC_INVERSE_MACROS.include?(reflection.macro) &&
643
- !INVALID_AUTOMATIC_INVERSE_OPTIONS.any? { |opt| reflection.options[opt] } &&
650
+ !reflection.options[:through] &&
651
+ !reflection.options[:foreign_key] &&
644
652
  !reflection.scope
645
653
  end
646
654
 
@@ -656,7 +664,7 @@ module ActiveRecord
656
664
  elsif options[:as]
657
665
  "#{options[:as]}_id"
658
666
  else
659
- active_record.name.foreign_key
667
+ active_record.model_name.to_s.foreign_key
660
668
  end
661
669
  end
662
670
 
@@ -691,11 +699,6 @@ module ActiveRecord
691
699
  Associations::HasOneAssociation
692
700
  end
693
701
  end
694
-
695
- private
696
- def calculate_constructable(macro, options)
697
- !options[:through]
698
- end
699
702
  end
700
703
 
701
704
  class BelongsToReflection < AssociationReflection # :nodoc:
@@ -736,10 +739,6 @@ module ActiveRecord
736
739
  def can_find_inverse_of_automatically?(_)
737
740
  !polymorphic? && super
738
741
  end
739
-
740
- def calculate_constructable(macro, options)
741
- !polymorphic?
742
- end
743
742
  end
744
743
 
745
744
  class HasAndBelongsToManyReflection < AssociationReflection # :nodoc:
@@ -752,7 +751,7 @@ module ActiveRecord
752
751
 
753
752
  # Holds all the metadata about a :through association as it was specified
754
753
  # in the Active Record class.
755
- class ThroughReflection < AbstractReflection #:nodoc:
754
+ class ThroughReflection < AbstractReflection # :nodoc:
756
755
  delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for, :type,
757
756
  :active_record_primary_key, :join_foreign_key, to: :source_reflection
758
757
 
@@ -760,6 +759,8 @@ module ActiveRecord
760
759
  @delegate_reflection = delegate_reflection
761
760
  @klass = delegate_reflection.options[:anonymous_class]
762
761
  @source_reflection_name = delegate_reflection.options[:source]
762
+
763
+ ensure_option_not_given_as_class!(:source_type)
763
764
  end
764
765
 
765
766
  def through_reflection?
@@ -840,8 +841,8 @@ module ActiveRecord
840
841
  source_reflection.scopes + super
841
842
  end
842
843
 
843
- def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
844
- source_reflection.join_scopes(table, predicate_builder, klass) + super
844
+ def join_scopes(table, predicate_builder, klass = self.klass, record = nil) # :nodoc:
845
+ source_reflection.join_scopes(table, predicate_builder, klass, record) + super
845
846
  end
846
847
 
847
848
  def has_scope?
@@ -1013,9 +1014,9 @@ module ActiveRecord
1013
1014
  @previous_reflection = previous_reflection
1014
1015
  end
1015
1016
 
1016
- def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
1017
- scopes = @previous_reflection.join_scopes(table, predicate_builder) + super
1018
- scopes << build_scope(table, predicate_builder, klass).instance_exec(nil, &source_type_scope)
1017
+ def join_scopes(table, predicate_builder, klass = self.klass, record = nil) # :nodoc:
1018
+ scopes = @previous_reflection.join_scopes(table, predicate_builder, record) + super
1019
+ scopes << build_scope(table, predicate_builder, klass).instance_exec(record, &source_type_scope)
1019
1020
  end
1020
1021
 
1021
1022
  def constraints