activerecord 6.1.7.6 → 7.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (251) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1570 -1016
  3. data/README.rdoc +3 -3
  4. data/lib/active_record/aggregations.rb +1 -1
  5. data/lib/active_record/association_relation.rb +0 -10
  6. data/lib/active_record/associations/association.rb +33 -17
  7. data/lib/active_record/associations/association_scope.rb +1 -3
  8. data/lib/active_record/associations/belongs_to_association.rb +15 -4
  9. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
  10. data/lib/active_record/associations/builder/association.rb +8 -2
  11. data/lib/active_record/associations/builder/belongs_to.rb +19 -6
  12. data/lib/active_record/associations/builder/collection_association.rb +10 -3
  13. data/lib/active_record/associations/builder/has_many.rb +3 -2
  14. data/lib/active_record/associations/builder/has_one.rb +2 -1
  15. data/lib/active_record/associations/builder/singular_association.rb +2 -2
  16. data/lib/active_record/associations/collection_association.rb +20 -22
  17. data/lib/active_record/associations/collection_proxy.rb +15 -5
  18. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  19. data/lib/active_record/associations/has_many_association.rb +8 -5
  20. data/lib/active_record/associations/has_many_through_association.rb +2 -1
  21. data/lib/active_record/associations/has_one_association.rb +10 -7
  22. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  23. data/lib/active_record/associations/join_dependency.rb +23 -15
  24. data/lib/active_record/associations/preloader/association.rb +186 -52
  25. data/lib/active_record/associations/preloader/batch.rb +48 -0
  26. data/lib/active_record/associations/preloader/branch.rb +147 -0
  27. data/lib/active_record/associations/preloader/through_association.rb +50 -14
  28. data/lib/active_record/associations/preloader.rb +39 -113
  29. data/lib/active_record/associations/singular_association.rb +8 -2
  30. data/lib/active_record/associations/through_association.rb +3 -3
  31. data/lib/active_record/associations.rb +138 -100
  32. data/lib/active_record/asynchronous_queries_tracker.rb +60 -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 +49 -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 +8 -6
  39. data/lib/active_record/attribute_methods/serialization.rb +57 -19
  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 +19 -22
  43. data/lib/active_record/attributes.rb +24 -35
  44. data/lib/active_record/autosave_association.rb +8 -23
  45. data/lib/active_record/base.rb +19 -1
  46. data/lib/active_record/callbacks.rb +14 -16
  47. data/lib/active_record/coders/yaml_column.rb +4 -8
  48. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +292 -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 +47 -561
  52. data/lib/active_record/connection_adapters/abstract/database_limits.rb +0 -17
  53. data/lib/active_record/connection_adapters/abstract/database_statements.rb +46 -22
  54. data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -12
  55. data/lib/active_record/connection_adapters/abstract/quoting.rb +42 -72
  56. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -17
  57. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +52 -23
  58. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
  59. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +82 -25
  60. data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -22
  61. data/lib/active_record/connection_adapters/abstract_adapter.rb +144 -82
  62. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +115 -85
  63. data/lib/active_record/connection_adapters/column.rb +4 -0
  64. data/lib/active_record/connection_adapters/mysql/database_statements.rb +37 -25
  65. data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -23
  66. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +4 -1
  67. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +7 -1
  68. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +20 -1
  69. data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -6
  70. data/lib/active_record/connection_adapters/pool_config.rb +7 -7
  71. data/lib/active_record/connection_adapters/postgresql/column.rb +19 -1
  72. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +20 -17
  73. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  74. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
  75. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
  76. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
  77. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
  78. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  79. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  80. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
  81. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  82. data/lib/active_record/connection_adapters/postgresql/quoting.rb +76 -73
  83. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +34 -0
  84. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +21 -1
  85. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +22 -1
  86. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +25 -0
  87. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +40 -21
  88. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
  89. data/lib/active_record/connection_adapters/postgresql_adapter.rb +207 -106
  90. data/lib/active_record/connection_adapters/schema_cache.rb +39 -38
  91. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +25 -19
  92. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +33 -18
  93. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -0
  94. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +19 -17
  95. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +98 -36
  96. data/lib/active_record/connection_adapters.rb +6 -5
  97. data/lib/active_record/connection_handling.rb +49 -55
  98. data/lib/active_record/core.rb +123 -148
  99. data/lib/active_record/database_configurations/connection_url_resolver.rb +2 -1
  100. data/lib/active_record/database_configurations/database_config.rb +12 -9
  101. data/lib/active_record/database_configurations/hash_config.rb +63 -5
  102. data/lib/active_record/database_configurations/url_config.rb +2 -2
  103. data/lib/active_record/database_configurations.rb +15 -32
  104. data/lib/active_record/delegated_type.rb +53 -12
  105. data/lib/active_record/destroy_association_async_job.rb +1 -1
  106. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  107. data/lib/active_record/dynamic_matchers.rb +1 -1
  108. data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
  109. data/lib/active_record/encryption/cipher.rb +53 -0
  110. data/lib/active_record/encryption/config.rb +44 -0
  111. data/lib/active_record/encryption/configurable.rb +67 -0
  112. data/lib/active_record/encryption/context.rb +35 -0
  113. data/lib/active_record/encryption/contexts.rb +72 -0
  114. data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
  115. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  116. data/lib/active_record/encryption/encryptable_record.rb +206 -0
  117. data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -0
  118. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  119. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  120. data/lib/active_record/encryption/encryptor.rb +155 -0
  121. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  122. data/lib/active_record/encryption/errors.rb +15 -0
  123. data/lib/active_record/encryption/extended_deterministic_queries.rb +160 -0
  124. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  125. data/lib/active_record/encryption/key.rb +28 -0
  126. data/lib/active_record/encryption/key_generator.rb +42 -0
  127. data/lib/active_record/encryption/key_provider.rb +46 -0
  128. data/lib/active_record/encryption/message.rb +33 -0
  129. data/lib/active_record/encryption/message_serializer.rb +90 -0
  130. data/lib/active_record/encryption/null_encryptor.rb +21 -0
  131. data/lib/active_record/encryption/properties.rb +76 -0
  132. data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
  133. data/lib/active_record/encryption/scheme.rb +99 -0
  134. data/lib/active_record/encryption.rb +55 -0
  135. data/lib/active_record/enum.rb +50 -43
  136. data/lib/active_record/errors.rb +67 -4
  137. data/lib/active_record/explain_registry.rb +11 -6
  138. data/lib/active_record/explain_subscriber.rb +1 -1
  139. data/lib/active_record/fixture_set/file.rb +15 -1
  140. data/lib/active_record/fixture_set/table_row.rb +41 -6
  141. data/lib/active_record/fixture_set/table_rows.rb +4 -4
  142. data/lib/active_record/fixtures.rb +20 -23
  143. data/lib/active_record/future_result.rb +139 -0
  144. data/lib/active_record/gem_version.rb +5 -5
  145. data/lib/active_record/inheritance.rb +55 -17
  146. data/lib/active_record/insert_all.rb +80 -14
  147. data/lib/active_record/integration.rb +4 -3
  148. data/lib/active_record/internal_metadata.rb +1 -5
  149. data/lib/active_record/legacy_yaml_adapter.rb +2 -39
  150. data/lib/active_record/locking/optimistic.rb +36 -21
  151. data/lib/active_record/locking/pessimistic.rb +10 -4
  152. data/lib/active_record/log_subscriber.rb +23 -7
  153. data/lib/active_record/middleware/database_selector/resolver.rb +6 -10
  154. data/lib/active_record/middleware/database_selector.rb +18 -6
  155. data/lib/active_record/middleware/shard_selector.rb +60 -0
  156. data/lib/active_record/migration/command_recorder.rb +8 -9
  157. data/lib/active_record/migration/compatibility.rb +93 -46
  158. data/lib/active_record/migration/join_table.rb +1 -1
  159. data/lib/active_record/migration.rb +167 -87
  160. data/lib/active_record/model_schema.rb +58 -59
  161. data/lib/active_record/nested_attributes.rb +13 -12
  162. data/lib/active_record/no_touching.rb +3 -3
  163. data/lib/active_record/null_relation.rb +2 -6
  164. data/lib/active_record/persistence.rb +231 -61
  165. data/lib/active_record/query_cache.rb +2 -2
  166. data/lib/active_record/query_logs.rb +149 -0
  167. data/lib/active_record/querying.rb +16 -6
  168. data/lib/active_record/railtie.rb +136 -22
  169. data/lib/active_record/railties/controller_runtime.rb +4 -5
  170. data/lib/active_record/railties/databases.rake +78 -136
  171. data/lib/active_record/readonly_attributes.rb +11 -0
  172. data/lib/active_record/reflection.rb +80 -49
  173. data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
  174. data/lib/active_record/relation/batches.rb +6 -6
  175. data/lib/active_record/relation/calculations.rb +92 -60
  176. data/lib/active_record/relation/delegation.rb +7 -7
  177. data/lib/active_record/relation/finder_methods.rb +31 -35
  178. data/lib/active_record/relation/merger.rb +20 -13
  179. data/lib/active_record/relation/predicate_builder/association_query_value.rb +20 -1
  180. data/lib/active_record/relation/predicate_builder.rb +1 -6
  181. data/lib/active_record/relation/query_attribute.rb +28 -11
  182. data/lib/active_record/relation/query_methods.rb +304 -68
  183. data/lib/active_record/relation/record_fetch_warning.rb +7 -9
  184. data/lib/active_record/relation/spawn_methods.rb +2 -2
  185. data/lib/active_record/relation/where_clause.rb +10 -19
  186. data/lib/active_record/relation.rb +189 -88
  187. data/lib/active_record/result.rb +23 -11
  188. data/lib/active_record/runtime_registry.rb +9 -13
  189. data/lib/active_record/sanitization.rb +17 -12
  190. data/lib/active_record/schema.rb +38 -23
  191. data/lib/active_record/schema_dumper.rb +29 -19
  192. data/lib/active_record/schema_migration.rb +4 -4
  193. data/lib/active_record/scoping/default.rb +60 -13
  194. data/lib/active_record/scoping/named.rb +3 -11
  195. data/lib/active_record/scoping.rb +64 -34
  196. data/lib/active_record/serialization.rb +6 -1
  197. data/lib/active_record/signed_id.rb +3 -3
  198. data/lib/active_record/store.rb +2 -2
  199. data/lib/active_record/suppressor.rb +11 -15
  200. data/lib/active_record/table_metadata.rb +6 -2
  201. data/lib/active_record/tasks/database_tasks.rb +127 -60
  202. data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
  203. data/lib/active_record/tasks/postgresql_database_tasks.rb +19 -13
  204. data/lib/active_record/test_databases.rb +1 -1
  205. data/lib/active_record/test_fixtures.rb +9 -6
  206. data/lib/active_record/timestamp.rb +3 -4
  207. data/lib/active_record/transactions.rb +12 -17
  208. data/lib/active_record/translation.rb +3 -3
  209. data/lib/active_record/type/adapter_specific_registry.rb +32 -7
  210. data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
  211. data/lib/active_record/type/internal/timezone.rb +2 -2
  212. data/lib/active_record/type/serialized.rb +9 -5
  213. data/lib/active_record/type/type_map.rb +17 -20
  214. data/lib/active_record/type.rb +1 -2
  215. data/lib/active_record/validations/associated.rb +4 -4
  216. data/lib/active_record/validations/presence.rb +2 -2
  217. data/lib/active_record/validations/uniqueness.rb +4 -4
  218. data/lib/active_record/version.rb +1 -1
  219. data/lib/active_record.rb +225 -27
  220. data/lib/arel/attributes/attribute.rb +0 -8
  221. data/lib/arel/crud.rb +28 -22
  222. data/lib/arel/delete_manager.rb +18 -4
  223. data/lib/arel/filter_predications.rb +9 -0
  224. data/lib/arel/insert_manager.rb +2 -3
  225. data/lib/arel/nodes/and.rb +4 -0
  226. data/lib/arel/nodes/casted.rb +1 -1
  227. data/lib/arel/nodes/delete_statement.rb +12 -13
  228. data/lib/arel/nodes/filter.rb +10 -0
  229. data/lib/arel/nodes/function.rb +1 -0
  230. data/lib/arel/nodes/insert_statement.rb +2 -2
  231. data/lib/arel/nodes/select_core.rb +2 -2
  232. data/lib/arel/nodes/select_statement.rb +2 -2
  233. data/lib/arel/nodes/update_statement.rb +8 -3
  234. data/lib/arel/nodes.rb +1 -0
  235. data/lib/arel/predications.rb +11 -3
  236. data/lib/arel/select_manager.rb +10 -4
  237. data/lib/arel/table.rb +0 -1
  238. data/lib/arel/tree_manager.rb +0 -12
  239. data/lib/arel/update_manager.rb +18 -4
  240. data/lib/arel/visitors/dot.rb +80 -90
  241. data/lib/arel/visitors/mysql.rb +8 -2
  242. data/lib/arel/visitors/postgresql.rb +0 -10
  243. data/lib/arel/visitors/to_sql.rb +58 -2
  244. data/lib/arel.rb +2 -1
  245. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  246. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
  247. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  248. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  249. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  250. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  251. metadata +55 -11
@@ -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"
@@ -307,7 +332,7 @@ db_namespace = namespace :db do
307
332
 
308
333
  desc "Retrieves the current schema version number"
309
334
  task version: :load_config do
310
- puts "Current version: #{ActiveRecord::Base.connection.migration_context.current_version}"
335
+ puts "Current version: #{ActiveRecord::Base.connection.schema_version}"
311
336
  end
312
337
 
313
338
  # desc "Raises an error if there are pending migrations"
@@ -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"
@@ -447,36 +452,32 @@ db_namespace = namespace :db do
447
452
  end
448
453
 
449
454
  namespace :schema do
450
- desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`)"
455
+ desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`)"
451
456
  task dump: :load_config do
452
457
  ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
453
- ActiveRecord::Base.establish_connection(db_config)
454
- ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config)
458
+ if db_config.schema_dump
459
+ ActiveRecord::Base.establish_connection(db_config)
460
+ schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
461
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, schema_format)
462
+ end
455
463
  end
456
464
 
457
465
  db_namespace["schema:dump"].reenable
458
466
  end
459
467
 
460
- desc "Loads a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) into the database"
468
+ desc "Loads a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`) into the database"
461
469
  task load: [:load_config, :check_protected_environments] do
462
- ActiveRecord::Tasks::DatabaseTasks.load_schema_current(ActiveRecord::Base.schema_format, ENV["SCHEMA"])
463
- end
464
-
465
- task load_if_ruby: ["db:create", :environment] do
466
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
467
- Using `bin/rails db:schema:load_if_ruby` is deprecated and will be removed in Rails 7.0.
468
- Configure the format using `config.active_record.schema_format = :ruby` to use `schema.rb` and run `bin/rails db:schema:load` instead.
469
- MSG
470
- db_namespace["schema:load"].invoke if ActiveRecord::Base.schema_format == :ruby
470
+ ActiveRecord::Tasks::DatabaseTasks.load_schema_current(ActiveRecord.schema_format, ENV["SCHEMA"])
471
471
  end
472
472
 
473
473
  namespace :dump do
474
474
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
475
- desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) for #{name} database"
475
+ desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`) for #{name} database"
476
476
  task name => :load_config do
477
477
  db_config = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, name: name)
478
478
  ActiveRecord::Base.establish_connection(db_config)
479
- ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config)
479
+ schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
480
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, schema_format)
480
481
  db_namespace["schema:dump:#{name}"].reenable
481
482
  end
482
483
  end
@@ -484,10 +485,14 @@ db_namespace = namespace :db do
484
485
 
485
486
  namespace :load do
486
487
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
487
- 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"
488
- task name => :load_config do
488
+ desc "Loads a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`) into the #{name} database"
489
+ task name => [:load_config, :check_protected_environments] do
490
+ original_db_config = ActiveRecord::Base.connection_db_config
489
491
  db_config = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, name: name)
490
- ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ActiveRecord::Base.schema_format, ENV["SCHEMA"])
492
+ schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
493
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
494
+ ensure
495
+ ActiveRecord::Base.establish_connection(original_db_config) if original_db_config
491
496
  end
492
497
  end
493
498
  end
@@ -523,60 +528,17 @@ db_namespace = namespace :db do
523
528
  end
524
529
  end
525
530
 
526
- namespace :structure do
527
- desc "Dumps the database structure to db/structure.sql. Specify another file with SCHEMA=db/my_structure.sql"
528
- task dump: :load_config do
529
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
530
- Using `bin/rails db:structure:dump` is deprecated and will be removed in Rails 7.0.
531
- Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:dump` instead.
532
- MSG
533
-
534
- db_namespace["schema:dump"].invoke
535
- db_namespace["structure:dump"].reenable
536
- end
531
+ namespace :encryption do
532
+ desc "Generate a set of keys for configuring Active Record encryption in a given environment"
533
+ task :init do
534
+ puts <<~MSG
535
+ Add this entry to the credentials of the target environment:#{' '}
537
536
 
538
- desc "Recreates the databases from the structure.sql file"
539
- task load: [:load_config, :check_protected_environments] do
540
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
541
- Using `bin/rails db:structure:load` is deprecated and will be removed in Rails 7.0.
542
- Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:load` instead.
537
+ active_record_encryption:
538
+ primary_key: #{SecureRandom.alphanumeric(32)}
539
+ deterministic_key: #{SecureRandom.alphanumeric(32)}
540
+ key_derivation_salt: #{SecureRandom.alphanumeric(32)}
543
541
  MSG
544
- db_namespace["schema:load"].invoke
545
- end
546
-
547
- task load_if_sql: ["db:create", :environment] do
548
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
549
- Using `bin/rails db:structure:load_if_sql` is deprecated and will be removed in Rails 7.0.
550
- Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:load` instead.
551
- MSG
552
- db_namespace["schema:load"].invoke if ActiveRecord::Base.schema_format == :sql
553
- end
554
-
555
- namespace :dump do
556
- ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
557
- desc "Dumps the #{name} database structure to db/structure.sql. Specify another file with SCHEMA=db/my_structure.sql"
558
- task name => :load_config do
559
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
560
- Using `bin/rails db:structure:dump:#{name}` is deprecated and will be removed in Rails 7.0.
561
- Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:dump:#{name}` instead.
562
- MSG
563
- db_namespace["schema:dump:#{name}"].invoke
564
- db_namespace["structure:dump:#{name}"].reenable
565
- end
566
- end
567
- end
568
-
569
- namespace :load do
570
- ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
571
- desc "Recreates the #{name} database from the structure.sql file"
572
- task name => :load_config do
573
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
574
- Using `bin/rails db:structure:load:#{name}` is deprecated and will be removed in Rails 7.0.
575
- Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:load:#{name}` instead.
576
- MSG
577
- db_namespace["schema:load:#{name}"].invoke
578
- end
579
- end
580
542
  end
581
543
  end
582
544
 
@@ -586,13 +548,13 @@ db_namespace = namespace :db do
586
548
  db_namespace["test:load_schema"].invoke
587
549
  end
588
550
 
589
- # desc "Recreate the test database from an existent schema file (schema.rb or structure.sql, depending on `config.active_record.schema_format`)"
551
+ # desc "Recreate the test database from an existent schema file (schema.rb or structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`)"
590
552
  task load_schema: %w(db:test:purge) do
591
553
  should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
592
554
  ActiveRecord::Schema.verbose = false
593
555
  ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
594
- filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(db_config.name)
595
- ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ActiveRecord::Base.schema_format, filename)
556
+ schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
557
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
596
558
  end
597
559
  ensure
598
560
  if should_reconnect
@@ -600,15 +562,6 @@ db_namespace = namespace :db do
600
562
  end
601
563
  end
602
564
 
603
- # desc "Recreate the test database from an existent structure.sql file"
604
- task load_structure: %w(db:test:purge) do
605
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
606
- Using `bin/rails db:test:load_structure` is deprecated and will be removed in Rails 7.0.
607
- Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:test:load_schema` instead.
608
- MSG
609
- db_namespace["test:load_schema"].invoke
610
- end
611
-
612
565
  # desc "Empty the test database"
613
566
  task purge: %w(load_config check_protected_environments) do
614
567
  ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
@@ -636,9 +589,9 @@ db_namespace = namespace :db do
636
589
  task name => "db:test:purge:#{name}" do
637
590
  should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
638
591
  ActiveRecord::Schema.verbose = false
639
- filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(name)
640
592
  db_config = ActiveRecord::Base.configurations.configs_for(env_name: "test", name: name)
641
- ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ActiveRecord::Base.schema_format, filename)
593
+ schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
594
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
642
595
  ensure
643
596
  if should_reconnect
644
597
  ActiveRecord::Base.establish_connection(ActiveRecord::Tasks::DatabaseTasks.env.to_sym)
@@ -646,17 +599,6 @@ db_namespace = namespace :db do
646
599
  end
647
600
  end
648
601
 
649
- # desc "Recreate the #{name} test database from an existent structure.sql file"
650
- namespace :load_structure do
651
- task name => "db:test:purge:#{name}" do
652
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
653
- Using `bin/rails db:test:load_structure:#{name}` is deprecated and will be removed in Rails 7.0.
654
- Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:test:load_structure:#{name}` instead.
655
- MSG
656
- db_namespace["test:load_schema:#{name}"].invoke
657
- end
658
- end
659
-
660
602
  # desc "Empty the #{name} test database"
661
603
  namespace :purge do
662
604
  task name => %w(load_config check_protected_environments) do
@@ -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
@@ -10,6 +10,7 @@ module ActiveRecord
10
10
  included do
11
11
  class_attribute :_reflections, instance_writer: false, default: {}
12
12
  class_attribute :aggregate_reflections, instance_writer: false, default: {}
13
+ class_attribute :automatic_scope_inversing, instance_writer: false, default: false
13
14
  end
14
15
 
15
16
  class << self
@@ -115,7 +116,7 @@ module ActiveRecord
115
116
  reflections[association.to_s]
116
117
  end
117
118
 
118
- def _reflect_on_association(association) #:nodoc:
119
+ def _reflect_on_association(association) # :nodoc:
119
120
  _reflections[association.to_s]
120
121
  end
121
122
 
@@ -194,9 +195,9 @@ module ActiveRecord
194
195
  klass_scope
195
196
  end
196
197
 
197
- def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
198
+ def join_scopes(table, predicate_builder, klass = self.klass, record = nil) # :nodoc:
198
199
  if scope
199
- [scope_for(build_scope(table, predicate_builder, klass))]
200
+ [scope_for(build_scope(table, predicate_builder, klass), record)]
200
201
  else
201
202
  []
202
203
  end
@@ -234,10 +235,13 @@ module ActiveRecord
234
235
  if has_inverse? && inverse_of.nil?
235
236
  raise InverseOfAssociationNotFoundError.new(self)
236
237
  end
238
+ if has_inverse? && inverse_of == self
239
+ raise InverseOfAssociationRecursiveError.new(self)
240
+ end
237
241
  end
238
242
  end
239
243
 
240
- # This shit is nasty. We need to avoid the following situation:
244
+ # We need to avoid the following situation:
241
245
  #
242
246
  # * An associated record is deleted via record.destroy
243
247
  # * Hence the callbacks run, and they find a belongs_to on the record with a
@@ -293,6 +297,12 @@ module ActiveRecord
293
297
  options[:strict_loading]
294
298
  end
295
299
 
300
+ def strict_loading_violation_message(owner)
301
+ message = +"`#{owner}` is marked for strict_loading."
302
+ message << " The #{polymorphic? ? "polymorphic association" : "#{klass} association"}"
303
+ message << " named `:#{name}` cannot be lazily loaded."
304
+ end
305
+
296
306
  protected
297
307
  def actual_source_reflection # FIXME: this is a horrible name
298
308
  self
@@ -306,6 +316,12 @@ module ActiveRecord
306
316
  def primary_key(klass)
307
317
  klass.primary_key || raise(UnknownPrimaryKey.new(klass))
308
318
  end
319
+
320
+ def ensure_option_not_given_as_class!(option_name)
321
+ if options[option_name] && options[option_name].class == Class
322
+ raise ArgumentError, "A class was passed to `:#{option_name}` but we are expecting a string."
323
+ end
324
+ end
309
325
  end
310
326
 
311
327
  # Base class for AggregateReflection and AssociationReflection. Objects of
@@ -392,7 +408,7 @@ module ActiveRecord
392
408
 
393
409
  # Holds all the metadata about an aggregation as it was specified in the
394
410
  # Active Record class.
395
- class AggregateReflection < MacroReflection #:nodoc:
411
+ class AggregateReflection < MacroReflection # :nodoc:
396
412
  def mapping
397
413
  mapping = options[:mapping] || [name, name]
398
414
  mapping.first.is_a?(Array) ? mapping : [mapping]
@@ -401,12 +417,29 @@ module ActiveRecord
401
417
 
402
418
  # Holds all the metadata about an association as it was specified in the
403
419
  # Active Record class.
404
- class AssociationReflection < MacroReflection #:nodoc:
420
+ class AssociationReflection < MacroReflection # :nodoc:
405
421
  def compute_class(name)
406
422
  if polymorphic?
407
423
  raise ArgumentError, "Polymorphic associations do not support computing the class."
408
424
  end
409
- active_record.send(:compute_type, name)
425
+
426
+ msg = <<-MSG.squish
427
+ Rails couldn't find a valid model for #{name} association.
428
+ Please provide the :class_name option on the association declaration.
429
+ If :class_name is already provided, make sure it's an ActiveRecord::Base subclass.
430
+ MSG
431
+
432
+ begin
433
+ klass = active_record.send(:compute_type, name)
434
+
435
+ unless klass < ActiveRecord::Base
436
+ raise ArgumentError, msg
437
+ end
438
+
439
+ klass
440
+ rescue NameError
441
+ raise NameError, msg
442
+ end
410
443
  end
411
444
 
412
445
  attr_reader :type, :foreign_type
@@ -416,11 +449,8 @@ module ActiveRecord
416
449
  super
417
450
  @type = -(options[:foreign_type]&.to_s || "#{options[:as]}_type") if options[:as]
418
451
  @foreign_type = -(options[:foreign_type]&.to_s || "#{name}_type") if options[:polymorphic]
419
- @constructable = calculate_constructable(macro, options)
420
452
 
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
453
+ ensure_option_not_given_as_class!(:class_name)
424
454
  end
425
455
 
426
456
  def association_scope_cache(klass, owner, &block)
@@ -431,10 +461,6 @@ module ActiveRecord
431
461
  klass.cached_find_by_statement(key, &block)
432
462
  end
433
463
 
434
- def constructable? # :nodoc:
435
- @constructable
436
- end
437
-
438
464
  def join_table
439
465
  @join_table ||= -(options[:join_table]&.to_s || derive_join_table)
440
466
  end
@@ -459,6 +485,10 @@ module ActiveRecord
459
485
  foreign_key
460
486
  end
461
487
 
488
+ def join_primary_type
489
+ type
490
+ end
491
+
462
492
  def join_foreign_key
463
493
  active_record_primary_key
464
494
  end
@@ -467,18 +497,17 @@ module ActiveRecord
467
497
  check_validity_of_inverse!
468
498
  end
469
499
 
470
- def check_preloadable!
500
+ def check_eager_loadable!
471
501
  return unless scope
472
502
 
473
503
  unless scope.arity == 0
474
504
  raise ArgumentError, <<-MSG.squish
475
505
  The association scope '#{name}' is instance dependent (the scope
476
- block takes an argument). Preloading instance dependent scopes is
477
- not supported.
506
+ block takes an argument). Eager loading instance dependent scopes
507
+ is not supported.
478
508
  MSG
479
509
  end
480
510
  end
481
- alias :check_eager_loadable! :check_preloadable!
482
511
 
483
512
  def join_id_for(owner) # :nodoc:
484
513
  owner[join_foreign_key]
@@ -563,8 +592,9 @@ module ActiveRecord
563
592
  options[:polymorphic]
564
593
  end
565
594
 
566
- VALID_AUTOMATIC_INVERSE_MACROS = [:has_many, :has_one, :belongs_to]
567
- INVALID_AUTOMATIC_INVERSE_OPTIONS = [:through, :foreign_key]
595
+ def polymorphic_name
596
+ active_record.polymorphic_name
597
+ end
568
598
 
569
599
  def add_as_source(seed)
570
600
  seed
@@ -583,10 +613,6 @@ module ActiveRecord
583
613
  end
584
614
 
585
615
  private
586
- def calculate_constructable(macro, options)
587
- true
588
- end
589
-
590
616
  # Attempts to find the inverse association name automatically.
591
617
  # If it cannot find a suitable inverse association name, it returns
592
618
  # +nil+.
@@ -623,9 +649,10 @@ module ActiveRecord
623
649
  # with the current reflection's klass name.
624
650
  def valid_inverse_reflection?(reflection)
625
651
  reflection &&
652
+ reflection != self &&
626
653
  foreign_key == reflection.foreign_key &&
627
654
  klass <= reflection.active_record &&
628
- can_find_inverse_of_automatically?(reflection)
655
+ can_find_inverse_of_automatically?(reflection, true)
629
656
  end
630
657
 
631
658
  # Checks to see if the reflection doesn't have any options that prevent
@@ -634,14 +661,25 @@ module ActiveRecord
634
661
  # have <tt>has_many</tt>, <tt>has_one</tt>, <tt>belongs_to</tt> associations.
635
662
  # Third, we must not have options such as <tt>:foreign_key</tt>
636
663
  # which prevent us from correctly guessing the inverse association.
637
- #
638
- # Anything with a scope can additionally ruin our attempt at finding an
639
- # inverse, so we exclude reflections with scopes.
640
- def can_find_inverse_of_automatically?(reflection)
664
+ def can_find_inverse_of_automatically?(reflection, inverse_reflection = false)
641
665
  reflection.options[:inverse_of] != false &&
642
- VALID_AUTOMATIC_INVERSE_MACROS.include?(reflection.macro) &&
643
- !INVALID_AUTOMATIC_INVERSE_OPTIONS.any? { |opt| reflection.options[opt] } &&
666
+ !reflection.options[:through] &&
667
+ !reflection.options[:foreign_key] &&
668
+ scope_allows_automatic_inverse_of?(reflection, inverse_reflection)
669
+ end
670
+
671
+ # Scopes on the potential inverse reflection prevent automatic
672
+ # <tt>inverse_of</tt>, since the scope could exclude the owner record
673
+ # we would inverse from. Scopes on the reflection itself allow for
674
+ # automatic <tt>inverse_of</tt> as long as
675
+ # <tt>config.active_record.automatic_scope_inversing<tt> is set to
676
+ # +true+ (the default for new applications).
677
+ def scope_allows_automatic_inverse_of?(reflection, inverse_reflection)
678
+ if inverse_reflection
644
679
  !reflection.scope
680
+ else
681
+ !reflection.scope || reflection.klass.automatic_scope_inversing
682
+ end
645
683
  end
646
684
 
647
685
  def derive_class_name
@@ -656,7 +694,7 @@ module ActiveRecord
656
694
  elsif options[:as]
657
695
  "#{options[:as]}_id"
658
696
  else
659
- active_record.name.foreign_key
697
+ active_record.model_name.to_s.foreign_key
660
698
  end
661
699
  end
662
700
 
@@ -691,11 +729,6 @@ module ActiveRecord
691
729
  Associations::HasOneAssociation
692
730
  end
693
731
  end
694
-
695
- private
696
- def calculate_constructable(macro, options)
697
- !options[:through]
698
- end
699
732
  end
700
733
 
701
734
  class BelongsToReflection < AssociationReflection # :nodoc:
@@ -733,13 +766,9 @@ module ActiveRecord
733
766
  end
734
767
 
735
768
  private
736
- def can_find_inverse_of_automatically?(_)
769
+ def can_find_inverse_of_automatically?(*)
737
770
  !polymorphic? && super
738
771
  end
739
-
740
- def calculate_constructable(macro, options)
741
- !polymorphic?
742
- end
743
772
  end
744
773
 
745
774
  class HasAndBelongsToManyReflection < AssociationReflection # :nodoc:
@@ -752,7 +781,7 @@ module ActiveRecord
752
781
 
753
782
  # Holds all the metadata about a :through association as it was specified
754
783
  # in the Active Record class.
755
- class ThroughReflection < AbstractReflection #:nodoc:
784
+ class ThroughReflection < AbstractReflection # :nodoc:
756
785
  delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for, :type,
757
786
  :active_record_primary_key, :join_foreign_key, to: :source_reflection
758
787
 
@@ -760,6 +789,8 @@ module ActiveRecord
760
789
  @delegate_reflection = delegate_reflection
761
790
  @klass = delegate_reflection.options[:anonymous_class]
762
791
  @source_reflection_name = delegate_reflection.options[:source]
792
+
793
+ ensure_option_not_given_as_class!(:source_type)
763
794
  end
764
795
 
765
796
  def through_reflection?
@@ -840,8 +871,8 @@ module ActiveRecord
840
871
  source_reflection.scopes + super
841
872
  end
842
873
 
843
- def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
844
- source_reflection.join_scopes(table, predicate_builder, klass) + super
874
+ def join_scopes(table, predicate_builder, klass = self.klass, record = nil) # :nodoc:
875
+ source_reflection.join_scopes(table, predicate_builder, klass, record) + super
845
876
  end
846
877
 
847
878
  def has_scope?
@@ -1013,9 +1044,9 @@ module ActiveRecord
1013
1044
  @previous_reflection = previous_reflection
1014
1045
  end
1015
1046
 
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)
1047
+ def join_scopes(table, predicate_builder, klass = self.klass, record = nil) # :nodoc:
1048
+ scopes = @previous_reflection.join_scopes(table, predicate_builder, klass, record) + super
1049
+ scopes << build_scope(table, predicate_builder, klass).instance_exec(record, &source_type_scope)
1019
1050
  end
1020
1051
 
1021
1052
  def constraints