activerecord 6.1.7 → 7.2.2

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 (333) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +616 -1290
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +31 -31
  5. data/examples/performance.rb +2 -2
  6. data/lib/active_record/aggregations.rb +17 -14
  7. data/lib/active_record/association_relation.rb +2 -12
  8. data/lib/active_record/associations/alias_tracker.rb +25 -19
  9. data/lib/active_record/associations/association.rb +60 -21
  10. data/lib/active_record/associations/association_scope.rb +17 -12
  11. data/lib/active_record/associations/belongs_to_association.rb +37 -11
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -4
  13. data/lib/active_record/associations/builder/association.rb +11 -5
  14. data/lib/active_record/associations/builder/belongs_to.rb +41 -14
  15. data/lib/active_record/associations/builder/collection_association.rb +10 -3
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -7
  17. data/lib/active_record/associations/builder/has_many.rb +4 -4
  18. data/lib/active_record/associations/builder/has_one.rb +4 -4
  19. data/lib/active_record/associations/builder/singular_association.rb +6 -2
  20. data/lib/active_record/associations/collection_association.rb +46 -36
  21. data/lib/active_record/associations/collection_proxy.rb +44 -16
  22. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  23. data/lib/active_record/associations/errors.rb +265 -0
  24. data/lib/active_record/associations/foreign_association.rb +10 -3
  25. data/lib/active_record/associations/has_many_association.rb +29 -19
  26. data/lib/active_record/associations/has_many_through_association.rb +19 -8
  27. data/lib/active_record/associations/has_one_association.rb +20 -10
  28. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  29. data/lib/active_record/associations/join_dependency/join_association.rb +30 -27
  30. data/lib/active_record/associations/join_dependency.rb +28 -20
  31. data/lib/active_record/associations/nested_error.rb +47 -0
  32. data/lib/active_record/associations/preloader/association.rb +212 -53
  33. data/lib/active_record/associations/preloader/batch.rb +48 -0
  34. data/lib/active_record/associations/preloader/branch.rb +153 -0
  35. data/lib/active_record/associations/preloader/through_association.rb +50 -16
  36. data/lib/active_record/associations/preloader.rb +50 -121
  37. data/lib/active_record/associations/singular_association.rb +15 -3
  38. data/lib/active_record/associations/through_association.rb +25 -14
  39. data/lib/active_record/associations.rb +429 -522
  40. data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
  41. data/lib/active_record/attribute_assignment.rb +1 -5
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
  43. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  44. data/lib/active_record/attribute_methods/dirty.rb +73 -22
  45. data/lib/active_record/attribute_methods/primary_key.rb +47 -27
  46. data/lib/active_record/attribute_methods/query.rb +31 -19
  47. data/lib/active_record/attribute_methods/read.rb +14 -11
  48. data/lib/active_record/attribute_methods/serialization.rb +174 -37
  49. data/lib/active_record/attribute_methods/time_zone_conversion.rb +15 -9
  50. data/lib/active_record/attribute_methods/write.rb +12 -15
  51. data/lib/active_record/attribute_methods.rb +164 -52
  52. data/lib/active_record/attributes.rb +57 -54
  53. data/lib/active_record/autosave_association.rb +74 -57
  54. data/lib/active_record/base.rb +27 -5
  55. data/lib/active_record/callbacks.rb +19 -35
  56. data/lib/active_record/coders/column_serializer.rb +61 -0
  57. data/lib/active_record/coders/json.rb +1 -1
  58. data/lib/active_record/coders/yaml_column.rb +70 -46
  59. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +284 -0
  60. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
  61. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +79 -0
  62. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +325 -604
  63. data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
  64. data/lib/active_record/connection_adapters/abstract/database_statements.rb +199 -60
  65. data/lib/active_record/connection_adapters/abstract/query_cache.rb +230 -64
  66. data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -131
  67. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  68. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +21 -20
  69. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +186 -31
  70. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
  71. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +378 -143
  72. data/lib/active_record/connection_adapters/abstract/transaction.rb +361 -76
  73. data/lib/active_record/connection_adapters/abstract_adapter.rb +624 -163
  74. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +348 -165
  75. data/lib/active_record/connection_adapters/column.rb +13 -0
  76. data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
  77. data/lib/active_record/connection_adapters/mysql/database_statements.rb +29 -130
  78. data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -55
  79. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
  80. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
  81. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
  82. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +45 -14
  83. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
  84. data/lib/active_record/connection_adapters/mysql2_adapter.rb +107 -68
  85. data/lib/active_record/connection_adapters/pool_config.rb +26 -16
  86. data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
  87. data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
  88. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +114 -54
  89. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
  94. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
  95. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
  96. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +12 -3
  97. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
  100. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
  101. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  102. data/lib/active_record/connection_adapters/postgresql/quoting.rb +137 -104
  103. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +28 -0
  104. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +92 -2
  105. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +173 -3
  106. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
  107. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +403 -77
  108. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
  109. data/lib/active_record/connection_adapters/postgresql_adapter.rb +520 -253
  110. data/lib/active_record/connection_adapters/schema_cache.rb +326 -102
  111. data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
  112. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +78 -55
  113. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +68 -54
  114. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  115. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +20 -0
  116. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
  117. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +66 -22
  118. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +372 -130
  119. data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
  120. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
  121. data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
  122. data/lib/active_record/connection_adapters.rb +130 -6
  123. data/lib/active_record/connection_handling.rb +132 -146
  124. data/lib/active_record/core.rb +310 -253
  125. data/lib/active_record/counter_cache.rb +68 -34
  126. data/lib/active_record/database_configurations/connection_url_resolver.rb +10 -4
  127. data/lib/active_record/database_configurations/database_config.rb +34 -10
  128. data/lib/active_record/database_configurations/hash_config.rb +107 -31
  129. data/lib/active_record/database_configurations/url_config.rb +38 -13
  130. data/lib/active_record/database_configurations.rb +96 -60
  131. data/lib/active_record/delegated_type.rb +90 -20
  132. data/lib/active_record/deprecator.rb +7 -0
  133. data/lib/active_record/destroy_association_async_job.rb +4 -2
  134. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  135. data/lib/active_record/dynamic_matchers.rb +3 -3
  136. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  137. data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
  138. data/lib/active_record/encryption/cipher.rb +53 -0
  139. data/lib/active_record/encryption/config.rb +68 -0
  140. data/lib/active_record/encryption/configurable.rb +60 -0
  141. data/lib/active_record/encryption/context.rb +42 -0
  142. data/lib/active_record/encryption/contexts.rb +76 -0
  143. data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
  144. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  145. data/lib/active_record/encryption/encryptable_record.rb +230 -0
  146. data/lib/active_record/encryption/encrypted_attribute_type.rb +175 -0
  147. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  148. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  149. data/lib/active_record/encryption/encryptor.rb +170 -0
  150. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  151. data/lib/active_record/encryption/errors.rb +15 -0
  152. data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
  153. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  154. data/lib/active_record/encryption/key.rb +28 -0
  155. data/lib/active_record/encryption/key_generator.rb +53 -0
  156. data/lib/active_record/encryption/key_provider.rb +46 -0
  157. data/lib/active_record/encryption/message.rb +33 -0
  158. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  159. data/lib/active_record/encryption/message_serializer.rb +96 -0
  160. data/lib/active_record/encryption/null_encryptor.rb +25 -0
  161. data/lib/active_record/encryption/properties.rb +76 -0
  162. data/lib/active_record/encryption/read_only_null_encryptor.rb +28 -0
  163. data/lib/active_record/encryption/scheme.rb +100 -0
  164. data/lib/active_record/encryption.rb +58 -0
  165. data/lib/active_record/enum.rb +170 -62
  166. data/lib/active_record/errors.rb +210 -27
  167. data/lib/active_record/explain.rb +21 -12
  168. data/lib/active_record/explain_registry.rb +11 -6
  169. data/lib/active_record/explain_subscriber.rb +1 -1
  170. data/lib/active_record/fixture_set/file.rb +15 -1
  171. data/lib/active_record/fixture_set/model_metadata.rb +14 -4
  172. data/lib/active_record/fixture_set/render_context.rb +2 -0
  173. data/lib/active_record/fixture_set/table_row.rb +70 -14
  174. data/lib/active_record/fixture_set/table_rows.rb +4 -4
  175. data/lib/active_record/fixtures.rb +179 -112
  176. data/lib/active_record/future_result.rb +178 -0
  177. data/lib/active_record/gem_version.rb +4 -4
  178. data/lib/active_record/inheritance.rb +85 -31
  179. data/lib/active_record/insert_all.rb +148 -32
  180. data/lib/active_record/integration.rb +14 -10
  181. data/lib/active_record/internal_metadata.rb +123 -23
  182. data/lib/active_record/legacy_yaml_adapter.rb +2 -39
  183. data/lib/active_record/locking/optimistic.rb +43 -27
  184. data/lib/active_record/locking/pessimistic.rb +15 -6
  185. data/lib/active_record/log_subscriber.rb +41 -29
  186. data/lib/active_record/marshalling.rb +59 -0
  187. data/lib/active_record/message_pack.rb +124 -0
  188. data/lib/active_record/middleware/database_selector/resolver.rb +10 -10
  189. data/lib/active_record/middleware/database_selector.rb +23 -13
  190. data/lib/active_record/middleware/shard_selector.rb +62 -0
  191. data/lib/active_record/migration/command_recorder.rb +113 -16
  192. data/lib/active_record/migration/compatibility.rb +235 -46
  193. data/lib/active_record/migration/default_strategy.rb +22 -0
  194. data/lib/active_record/migration/execution_strategy.rb +19 -0
  195. data/lib/active_record/migration/join_table.rb +1 -1
  196. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  197. data/lib/active_record/migration.rb +374 -177
  198. data/lib/active_record/model_schema.rb +145 -158
  199. data/lib/active_record/nested_attributes.rb +61 -23
  200. data/lib/active_record/no_touching.rb +3 -3
  201. data/lib/active_record/normalization.rb +163 -0
  202. data/lib/active_record/persistence.rb +282 -283
  203. data/lib/active_record/promise.rb +84 -0
  204. data/lib/active_record/query_cache.rb +18 -25
  205. data/lib/active_record/query_logs.rb +189 -0
  206. data/lib/active_record/query_logs_formatter.rb +41 -0
  207. data/lib/active_record/querying.rb +44 -9
  208. data/lib/active_record/railtie.rb +229 -71
  209. data/lib/active_record/railties/controller_runtime.rb +25 -11
  210. data/lib/active_record/railties/databases.rake +189 -256
  211. data/lib/active_record/railties/job_runtime.rb +23 -0
  212. data/lib/active_record/readonly_attributes.rb +41 -3
  213. data/lib/active_record/reflection.rb +332 -103
  214. data/lib/active_record/relation/batches/batch_enumerator.rb +38 -9
  215. data/lib/active_record/relation/batches.rb +200 -65
  216. data/lib/active_record/relation/calculations.rb +301 -112
  217. data/lib/active_record/relation/delegation.rb +33 -22
  218. data/lib/active_record/relation/finder_methods.rb +123 -52
  219. data/lib/active_record/relation/merger.rb +26 -19
  220. data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
  221. data/lib/active_record/relation/predicate_builder/association_query_value.rb +38 -4
  222. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -7
  223. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  224. data/lib/active_record/relation/predicate_builder.rb +29 -22
  225. data/lib/active_record/relation/query_attribute.rb +30 -12
  226. data/lib/active_record/relation/query_methods.rb +870 -163
  227. data/lib/active_record/relation/record_fetch_warning.rb +10 -9
  228. data/lib/active_record/relation/spawn_methods.rb +7 -6
  229. data/lib/active_record/relation/where_clause.rb +15 -36
  230. data/lib/active_record/relation.rb +736 -145
  231. data/lib/active_record/result.rb +67 -54
  232. data/lib/active_record/runtime_registry.rb +71 -13
  233. data/lib/active_record/sanitization.rb +84 -34
  234. data/lib/active_record/schema.rb +39 -23
  235. data/lib/active_record/schema_dumper.rb +90 -31
  236. data/lib/active_record/schema_migration.rb +74 -23
  237. data/lib/active_record/scoping/default.rb +72 -15
  238. data/lib/active_record/scoping/named.rb +6 -13
  239. data/lib/active_record/scoping.rb +65 -34
  240. data/lib/active_record/secure_password.rb +60 -0
  241. data/lib/active_record/secure_token.rb +21 -3
  242. data/lib/active_record/serialization.rb +6 -1
  243. data/lib/active_record/signed_id.rb +30 -9
  244. data/lib/active_record/statement_cache.rb +7 -7
  245. data/lib/active_record/store.rb +10 -10
  246. data/lib/active_record/suppressor.rb +13 -15
  247. data/lib/active_record/table_metadata.rb +7 -3
  248. data/lib/active_record/tasks/database_tasks.rb +288 -149
  249. data/lib/active_record/tasks/mysql_database_tasks.rb +16 -7
  250. data/lib/active_record/tasks/postgresql_database_tasks.rb +35 -26
  251. data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -7
  252. data/lib/active_record/test_databases.rb +1 -1
  253. data/lib/active_record/test_fixtures.rb +173 -155
  254. data/lib/active_record/testing/query_assertions.rb +121 -0
  255. data/lib/active_record/timestamp.rb +32 -19
  256. data/lib/active_record/token_for.rb +123 -0
  257. data/lib/active_record/touch_later.rb +12 -7
  258. data/lib/active_record/transaction.rb +132 -0
  259. data/lib/active_record/transactions.rb +118 -41
  260. data/lib/active_record/translation.rb +3 -5
  261. data/lib/active_record/type/adapter_specific_registry.rb +32 -14
  262. data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
  263. data/lib/active_record/type/internal/timezone.rb +7 -2
  264. data/lib/active_record/type/serialized.rb +9 -7
  265. data/lib/active_record/type/time.rb +4 -0
  266. data/lib/active_record/type/type_map.rb +17 -20
  267. data/lib/active_record/type.rb +1 -2
  268. data/lib/active_record/type_caster/connection.rb +4 -4
  269. data/lib/active_record/validations/absence.rb +1 -1
  270. data/lib/active_record/validations/associated.rb +13 -7
  271. data/lib/active_record/validations/numericality.rb +5 -4
  272. data/lib/active_record/validations/presence.rb +5 -28
  273. data/lib/active_record/validations/uniqueness.rb +65 -15
  274. data/lib/active_record/validations.rb +12 -5
  275. data/lib/active_record/version.rb +1 -1
  276. data/lib/active_record.rb +444 -32
  277. data/lib/arel/alias_predication.rb +1 -1
  278. data/lib/arel/attributes/attribute.rb +0 -8
  279. data/lib/arel/collectors/bind.rb +2 -0
  280. data/lib/arel/collectors/composite.rb +7 -0
  281. data/lib/arel/collectors/sql_string.rb +1 -1
  282. data/lib/arel/collectors/substitute_binds.rb +1 -1
  283. data/lib/arel/crud.rb +28 -22
  284. data/lib/arel/delete_manager.rb +18 -4
  285. data/lib/arel/errors.rb +10 -0
  286. data/lib/arel/factory_methods.rb +4 -0
  287. data/lib/arel/filter_predications.rb +9 -0
  288. data/lib/arel/insert_manager.rb +2 -3
  289. data/lib/arel/nodes/binary.rb +6 -7
  290. data/lib/arel/nodes/bound_sql_literal.rb +65 -0
  291. data/lib/arel/nodes/casted.rb +1 -1
  292. data/lib/arel/nodes/cte.rb +36 -0
  293. data/lib/arel/nodes/delete_statement.rb +12 -13
  294. data/lib/arel/nodes/filter.rb +10 -0
  295. data/lib/arel/nodes/fragments.rb +35 -0
  296. data/lib/arel/nodes/function.rb +1 -0
  297. data/lib/arel/nodes/homogeneous_in.rb +1 -9
  298. data/lib/arel/nodes/insert_statement.rb +2 -2
  299. data/lib/arel/nodes/leading_join.rb +8 -0
  300. data/lib/arel/nodes/{and.rb → nary.rb} +9 -2
  301. data/lib/arel/nodes/node.rb +115 -5
  302. data/lib/arel/nodes/select_core.rb +2 -2
  303. data/lib/arel/nodes/select_statement.rb +2 -2
  304. data/lib/arel/nodes/sql_literal.rb +13 -0
  305. data/lib/arel/nodes/table_alias.rb +4 -0
  306. data/lib/arel/nodes/update_statement.rb +8 -3
  307. data/lib/arel/nodes.rb +7 -2
  308. data/lib/arel/predications.rb +14 -4
  309. data/lib/arel/select_manager.rb +11 -5
  310. data/lib/arel/table.rb +9 -6
  311. data/lib/arel/tree_manager.rb +8 -15
  312. data/lib/arel/update_manager.rb +20 -5
  313. data/lib/arel/visitors/dot.rb +81 -90
  314. data/lib/arel/visitors/mysql.rb +23 -5
  315. data/lib/arel/visitors/postgresql.rb +1 -22
  316. data/lib/arel/visitors/sqlite.rb +25 -0
  317. data/lib/arel/visitors/to_sql.rb +170 -36
  318. data/lib/arel/visitors/visitor.rb +2 -2
  319. data/lib/arel.rb +23 -4
  320. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  321. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  322. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
  323. data/lib/rails/generators/active_record/migration.rb +3 -1
  324. data/lib/rails/generators/active_record/model/USAGE +113 -0
  325. data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
  326. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
  327. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  328. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  329. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  330. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  331. metadata +103 -17
  332. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
  333. data/lib/active_record/null_relation.rb +0 -67
@@ -6,6 +6,13 @@ module ActiveRecord
6
6
  module ModelSchema
7
7
  extend ActiveSupport::Concern
8
8
 
9
+ ##
10
+ # :method: id_value
11
+ # :call-seq: id_value
12
+ #
13
+ # Returns the underlying column value for a column named "id". Useful when defining
14
+ # a composite primary key including an "id" column so that the value is readable.
15
+
9
16
  ##
10
17
  # :singleton-method: primary_key_prefix_type
11
18
  # :call-seq: primary_key_prefix_type
@@ -126,9 +133,34 @@ module ActiveRecord
126
133
  # +:immutable_string+. This setting does not affect the behavior of
127
134
  # <tt>attribute :foo, :string</tt>. Defaults to false.
128
135
 
129
- included do
130
- mattr_accessor :primary_key_prefix_type, instance_writer: false
136
+ ##
137
+ # :singleton-method: inheritance_column
138
+ # :call-seq: inheritance_column
139
+ #
140
+ # The name of the table column which stores the class name on single-table
141
+ # inheritance situations.
142
+ #
143
+ # The default inheritance column name is +type+, which means it's a
144
+ # reserved word inside Active Record. To be able to use single-table
145
+ # inheritance with another column name, or to use the column +type+ in
146
+ # your own model for something else, you can set +inheritance_column+:
147
+ #
148
+ # self.inheritance_column = 'zoink'
149
+ #
150
+ # If you wish to disable single-table inheritance altogether you can set
151
+ # +inheritance_column+ to +nil+
152
+ #
153
+ # self.inheritance_column = nil
154
+
155
+ ##
156
+ # :singleton-method: inheritance_column=
157
+ # :call-seq: inheritance_column=(column)
158
+ #
159
+ # Defines the name of the table column which will store the class name on single-table
160
+ # inheritance situations.
131
161
 
162
+ included do
163
+ class_attribute :primary_key_prefix_type, instance_writer: false
132
164
  class_attribute :table_name_prefix, instance_writer: false, default: ""
133
165
  class_attribute :table_name_suffix, instance_writer: false, default: ""
134
166
  class_attribute :schema_migrations_table_name, instance_accessor: false, default: "schema_migrations"
@@ -137,8 +169,15 @@ module ActiveRecord
137
169
  class_attribute :implicit_order_column, instance_accessor: false
138
170
  class_attribute :immutable_strings_by_default, instance_accessor: false
139
171
 
172
+ class_attribute :inheritance_column, instance_accessor: false, default: "type"
173
+ singleton_class.class_eval do
174
+ alias_method :_inheritance_column=, :inheritance_column=
175
+ private :_inheritance_column=
176
+ alias_method :inheritance_column=, :real_inheritance_column=
177
+ end
178
+
140
179
  self.protected_environments = ["production"]
141
- self.inheritance_column = "type"
180
+
142
181
  self.ignored_columns = [].freeze
143
182
 
144
183
  delegate :type_for_attribute, :column_for_attribute, to: :class
@@ -153,8 +192,9 @@ module ActiveRecord
153
192
  # artists, records => artists_records
154
193
  # records, artists => artists_records
155
194
  # music_artists, music_records => music_artists_records
195
+ # music.artists, music.records => music.artists_records
156
196
  def self.derive_join_table_name(first_table, second_table) # :nodoc:
157
- [first_table.to_s, second_table.to_s].sort.join("\0").gsub(/^(.*_)(.+)\0\1(.+)/, '\1\2_\3').tr("\0", "_")
197
+ [first_table.to_s, second_table.to_s].sort.join("\0").gsub(/^(.*[_.])(.+)\0\1(.+)/, '\1\2_\3').tr("\0", "_")
158
198
  end
159
199
 
160
200
  module ClassMethods
@@ -197,6 +237,21 @@ module ActiveRecord
197
237
  # the table name guess for an Invoice class becomes "myapp_invoices".
198
238
  # Invoice::Lineitem becomes "myapp_invoice_lineitems".
199
239
  #
240
+ # Active Model Naming's +model_name+ is the base name used to guess the
241
+ # table name. In case a custom Active Model Name is defined, it will be
242
+ # used for the table name as well:
243
+ #
244
+ # class PostRecord < ActiveRecord::Base
245
+ # class << self
246
+ # def model_name
247
+ # ActiveModel::Name.new(self, nil, "Post")
248
+ # end
249
+ # end
250
+ # end
251
+ #
252
+ # PostRecord.table_name
253
+ # # => "posts"
254
+ #
200
255
  # You can also set your own table name explicitly:
201
256
  #
202
257
  # class Mouse < ActiveRecord::Base
@@ -223,19 +278,21 @@ module ActiveRecord
223
278
  @table_name = value
224
279
  @quoted_table_name = nil
225
280
  @arel_table = nil
226
- @sequence_name = nil unless defined?(@explicit_sequence_name) && @explicit_sequence_name
281
+ @sequence_name = nil unless @explicit_sequence_name
227
282
  @predicate_builder = nil
228
283
  end
229
284
 
230
285
  # Returns a quoted version of the table name, used to construct SQL statements.
231
286
  def quoted_table_name
232
- @quoted_table_name ||= connection.quote_table_name(table_name)
287
+ @quoted_table_name ||= adapter_class.quote_table_name(table_name)
233
288
  end
234
289
 
235
290
  # Computes the table name, (re)sets it internally, and returns it.
236
- def reset_table_name #:nodoc:
237
- self.table_name = if abstract_class?
238
- superclass == Base ? nil : superclass.table_name
291
+ def reset_table_name # :nodoc:
292
+ self.table_name = if self == Base
293
+ nil
294
+ elsif abstract_class?
295
+ superclass.table_name
239
296
  elsif superclass.abstract_class?
240
297
  superclass.table_name || compute_table_name
241
298
  else
@@ -243,11 +300,11 @@ module ActiveRecord
243
300
  end
244
301
  end
245
302
 
246
- def full_table_name_prefix #:nodoc:
303
+ def full_table_name_prefix # :nodoc:
247
304
  (module_parents.detect { |p| p.respond_to?(:table_name_prefix) } || self).table_name_prefix
248
305
  end
249
306
 
250
- def full_table_name_suffix #:nodoc:
307
+ def full_table_name_suffix # :nodoc:
251
308
  (module_parents.detect { |p| p.respond_to?(:table_name_suffix) } || self).table_name_suffix
252
309
  end
253
310
 
@@ -266,33 +323,14 @@ module ActiveRecord
266
323
  @protected_environments = environments.map(&:to_s)
267
324
  end
268
325
 
269
- # Defines the name of the table column which will store the class name on single-table
270
- # inheritance situations.
271
- #
272
- # The default inheritance column name is +type+, which means it's a
273
- # reserved word inside Active Record. To be able to use single-table
274
- # inheritance with another column name, or to use the column +type+ in
275
- # your own model for something else, you can set +inheritance_column+:
276
- #
277
- # self.inheritance_column = 'zoink'
278
- def inheritance_column
279
- (@inheritance_column ||= nil) || superclass.inheritance_column
280
- end
281
-
282
- # Sets the value of inheritance_column
283
- def inheritance_column=(value)
284
- @inheritance_column = value.to_s
285
- @explicit_inheritance_column = true
326
+ def real_inheritance_column=(value) # :nodoc:
327
+ self._inheritance_column = value.to_s
286
328
  end
287
329
 
288
330
  # The list of columns names the model should ignore. Ignored columns won't have attribute
289
331
  # accessors defined, and won't be referenced in SQL queries.
290
332
  def ignored_columns
291
- if defined?(@ignored_columns)
292
- @ignored_columns
293
- else
294
- superclass.ignored_columns
295
- end
333
+ @ignored_columns || superclass.ignored_columns
296
334
  end
297
335
 
298
336
  # Sets the columns names the model should ignore. Ignored columns won't have attribute
@@ -313,7 +351,7 @@ module ActiveRecord
313
351
  # # name :string, limit: 255
314
352
  # # category :string, limit: 255
315
353
  #
316
- # self.ignored_columns = [:category]
354
+ # self.ignored_columns += [:category]
317
355
  # end
318
356
  #
319
357
  # The schema still contains "category", but now the model omits it, so any meta-driven code or
@@ -339,9 +377,9 @@ module ActiveRecord
339
377
  end
340
378
  end
341
379
 
342
- def reset_sequence_name #:nodoc:
380
+ def reset_sequence_name # :nodoc:
343
381
  @explicit_sequence_name = false
344
- @sequence_name = connection.default_sequence_name(table_name, primary_key)
382
+ @sequence_name = with_connection { |c| c.default_sequence_name(table_name, primary_key) }
345
383
  end
346
384
 
347
385
  # Sets the name of the sequence to use when generating ids to the given
@@ -366,71 +404,52 @@ module ActiveRecord
366
404
  # Determines if the primary key values should be selected from their
367
405
  # corresponding sequence before the insert statement.
368
406
  def prefetch_primary_key?
369
- connection.prefetch_primary_key?(table_name)
407
+ with_connection { |c| c.prefetch_primary_key?(table_name) }
370
408
  end
371
409
 
372
410
  # Returns the next value that will be used as the primary key on
373
411
  # an insert statement.
374
412
  def next_sequence_value
375
- connection.next_sequence_value(sequence_name)
413
+ with_connection { |c| c.next_sequence_value(sequence_name) }
376
414
  end
377
415
 
378
416
  # Indicates whether the table associated with this class exists
379
417
  def table_exists?
380
- connection.schema_cache.data_source_exists?(table_name)
418
+ schema_cache.data_source_exists?(table_name)
381
419
  end
382
420
 
383
421
  def attributes_builder # :nodoc:
384
- unless defined?(@attributes_builder) && @attributes_builder
422
+ @attributes_builder ||= begin
385
423
  defaults = _default_attributes.except(*(column_names - [primary_key]))
386
- @attributes_builder = ActiveModel::AttributeSet::Builder.new(attribute_types, defaults)
424
+ ActiveModel::AttributeSet::Builder.new(attribute_types, defaults)
387
425
  end
388
- @attributes_builder
389
426
  end
390
427
 
391
428
  def columns_hash # :nodoc:
392
- load_schema
429
+ load_schema unless @columns_hash
393
430
  @columns_hash
394
431
  end
395
432
 
396
433
  def columns
397
- load_schema
398
434
  @columns ||= columns_hash.values.freeze
399
435
  end
400
436
 
401
- def attribute_types # :nodoc:
402
- load_schema
403
- @attribute_types ||= Hash.new(Type.default_value)
437
+ def _returning_columns_for_insert(connection) # :nodoc:
438
+ @_returning_columns_for_insert ||= begin
439
+ auto_populated_columns = columns.filter_map do |c|
440
+ c.name if connection.return_value_after_insert?(c)
441
+ end
442
+
443
+ auto_populated_columns.empty? ? Array(primary_key) : auto_populated_columns
444
+ end
404
445
  end
405
446
 
406
447
  def yaml_encoder # :nodoc:
407
448
  @yaml_encoder ||= ActiveModel::AttributeSet::YAMLEncoder.new(attribute_types)
408
449
  end
409
450
 
410
- # Returns the type of the attribute with the given name, after applying
411
- # all modifiers. This method is the only valid source of information for
412
- # anything related to the types of a model's attributes. This method will
413
- # access the database and load the model's schema if it is required.
414
- #
415
- # The return value of this method will implement the interface described
416
- # by ActiveModel::Type::Value (though the object itself may not subclass
417
- # it).
418
- #
419
- # +attr_name+ The name of the attribute to retrieve the type for. Must be
420
- # a string or a symbol.
421
- def type_for_attribute(attr_name, &block)
422
- attr_name = attr_name.to_s
423
- attr_name = attribute_aliases[attr_name] || attr_name
424
-
425
- if block
426
- attribute_types.fetch(attr_name, &block)
427
- else
428
- attribute_types[attr_name]
429
- end
430
- end
431
-
432
451
  # Returns the column object for the named attribute.
433
- # Returns an +ActiveRecord::ConnectionAdapters::NullColumn+ if the
452
+ # Returns an ActiveRecord::ConnectionAdapters::NullColumn if the
434
453
  # named attribute does not exist.
435
454
  #
436
455
  # class Person < ActiveRecord::Base
@@ -456,11 +475,6 @@ module ActiveRecord
456
475
  @column_defaults ||= _default_attributes.deep_dup.to_hash.freeze
457
476
  end
458
477
 
459
- def _default_attributes # :nodoc:
460
- load_schema
461
- @default_attributes ||= ActiveModel::AttributeSet.new({})
462
- end
463
-
464
478
  # Returns an array of column names as strings.
465
479
  def column_names
466
480
  @column_names ||= columns.map(&:name).freeze
@@ -486,9 +500,9 @@ module ActiveRecord
486
500
  #
487
501
  # The most common usage pattern for this method is probably in a migration,
488
502
  # when just after creating a table you want to populate it with some default
489
- # values, eg:
503
+ # values, e.g.:
490
504
  #
491
- # class CreateJobLevels < ActiveRecord::Migration[6.0]
505
+ # class CreateJobLevels < ActiveRecord::Migration[7.2]
492
506
  # def up
493
507
  # create_table :job_levels do |t|
494
508
  # t.integer :id
@@ -508,41 +522,67 @@ module ActiveRecord
508
522
  # end
509
523
  # end
510
524
  def reset_column_information
511
- connection.clear_cache!
525
+ connection_pool.active_connection&.clear_cache!
512
526
  ([self] + descendants).each(&:undefine_attribute_methods)
513
- connection.schema_cache.clear_data_source_cache!(table_name)
527
+ schema_cache.clear_data_source_cache!(table_name)
514
528
 
515
529
  reload_schema_from_cache
516
530
  initialize_find_by_cache
517
531
  end
518
532
 
533
+ # Load the model's schema information either from the schema cache
534
+ # or directly from the database.
535
+ def load_schema
536
+ return if schema_loaded?
537
+ @load_schema_monitor.synchronize do
538
+ return if schema_loaded?
539
+
540
+ load_schema!
541
+
542
+ @schema_loaded = true
543
+ rescue
544
+ reload_schema_from_cache # If the schema loading failed half way through, we must reset the state.
545
+ raise
546
+ end
547
+ end
548
+
519
549
  protected
520
550
  def initialize_load_schema_monitor
521
551
  @load_schema_monitor = Monitor.new
522
552
  end
523
553
 
554
+ def reload_schema_from_cache(recursive = true)
555
+ @_returning_columns_for_insert = nil
556
+ @arel_table = nil
557
+ @column_names = nil
558
+ @symbol_column_to_string_name_hash = nil
559
+ @content_columns = nil
560
+ @column_defaults = nil
561
+ @attributes_builder = nil
562
+ @columns = nil
563
+ @columns_hash = nil
564
+ @schema_loaded = false
565
+ @attribute_names = nil
566
+ @yaml_encoder = nil
567
+ if recursive
568
+ subclasses.each do |descendant|
569
+ descendant.send(:reload_schema_from_cache)
570
+ end
571
+ end
572
+ end
573
+
524
574
  private
525
575
  def inherited(child_class)
526
576
  super
527
577
  child_class.initialize_load_schema_monitor
578
+ child_class.reload_schema_from_cache(false)
579
+ child_class.class_eval do
580
+ @ignored_columns = nil
581
+ end
528
582
  end
529
583
 
530
584
  def schema_loaded?
531
- defined?(@schema_loaded) && @schema_loaded
532
- end
533
-
534
- def load_schema
535
- return if schema_loaded?
536
- @load_schema_monitor.synchronize do
537
- return if defined?(@columns_hash) && @columns_hash
538
-
539
- load_schema!
540
-
541
- @schema_loaded = true
542
- rescue
543
- reload_schema_from_cache # If the schema loading failed half way through, we must reset the state.
544
- raise
545
- end
585
+ @schema_loaded
546
586
  end
547
587
 
548
588
  def load_schema!
@@ -550,45 +590,16 @@ module ActiveRecord
550
590
  raise ActiveRecord::TableNotSpecified, "#{self} has no table configured. Set one with #{self}.table_name="
551
591
  end
552
592
 
553
- columns_hash = connection.schema_cache.columns_hash(table_name)
593
+ columns_hash = schema_cache.columns_hash(table_name)
554
594
  columns_hash = columns_hash.except(*ignored_columns) unless ignored_columns.empty?
555
595
  @columns_hash = columns_hash.freeze
556
- @columns_hash.each do |name, column|
557
- type = connection.lookup_cast_type_from_column(column)
558
- type = _convert_type_from_options(type)
559
- warn_if_deprecated_type(column)
560
- define_attribute(
561
- name,
562
- type,
563
- default: column.default,
564
- user_provided_default: false
565
- )
566
- end
567
- end
568
596
 
569
- def reload_schema_from_cache
570
- @arel_table = nil
571
- @column_names = nil
572
- @symbol_column_to_string_name_hash = nil
573
- @attribute_types = nil
574
- @content_columns = nil
575
- @default_attributes = nil
576
- @column_defaults = nil
577
- @inheritance_column = nil unless defined?(@explicit_inheritance_column) && @explicit_inheritance_column
578
- @attributes_builder = nil
579
- @columns = nil
580
- @columns_hash = nil
581
- @schema_loaded = false
582
- @attribute_names = nil
583
- @yaml_encoder = nil
584
- direct_descendants.each do |descendant|
585
- descendant.send(:reload_schema_from_cache)
586
- end
597
+ _default_attributes # Precompute to cache DB-dependent attribute types
587
598
  end
588
599
 
589
600
  # Guesses the table name, but does not decorate it with prefix and suffix information.
590
- def undecorated_table_name(class_name = base_class.name)
591
- table_name = class_name.to_s.demodulize.underscore
601
+ def undecorated_table_name(model_name)
602
+ table_name = model_name.to_s.demodulize.underscore
592
603
  pluralize_table_names ? table_name.pluralize : table_name
593
604
  end
594
605
 
@@ -602,45 +613,21 @@ module ActiveRecord
602
613
  contained += "_"
603
614
  end
604
615
 
605
- "#{full_table_name_prefix}#{contained}#{undecorated_table_name(name)}#{full_table_name_suffix}"
616
+ "#{full_table_name_prefix}#{contained}#{undecorated_table_name(model_name)}#{full_table_name_suffix}"
606
617
  else
607
- # STI subclasses always use their superclass' table.
618
+ # STI subclasses always use their superclass's table.
608
619
  base_class.table_name
609
620
  end
610
621
  end
611
622
 
612
- def _convert_type_from_options(type)
613
- if immutable_strings_by_default && type.respond_to?(:to_immutable_string)
614
- type.to_immutable_string
615
- else
616
- type
617
- end
618
- end
619
-
620
- def warn_if_deprecated_type(column)
621
- return if attributes_to_define_after_schema_loads.key?(column.name)
622
- return unless column.respond_to?(:oid)
623
+ def type_for_column(connection, column)
624
+ type = connection.lookup_cast_type_from_column(column)
623
625
 
624
- if column.array?
625
- array_arguments = ", array: true"
626
- else
627
- array_arguments = ""
626
+ if immutable_strings_by_default && type.respond_to?(:to_immutable_string)
627
+ type = type.to_immutable_string
628
628
  end
629
629
 
630
- if column.sql_type.start_with?("interval")
631
- precision_arguments = column.precision.presence && ", precision: #{column.precision}"
632
- ActiveSupport::Deprecation.warn(<<~WARNING)
633
- The behavior of the `:interval` type will be changing in Rails 7.0
634
- to return an `ActiveSupport::Duration` object. If you'd like to keep
635
- the old behavior, you can add this line to #{self.name} model:
636
-
637
- attribute :#{column.name}, :string#{precision_arguments}#{array_arguments}
638
-
639
- If you'd like the new behavior today, you can add this line:
640
-
641
- attribute :#{column.name}, :interval#{precision_arguments}#{array_arguments}
642
- WARNING
643
- end
630
+ type
644
631
  end
645
632
  end
646
633
  end