activerecord 6.0.0 → 7.2.3

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 (376) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +996 -594
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +34 -34
  5. data/examples/performance.rb +2 -2
  6. data/lib/active_record/aggregations.rb +22 -20
  7. data/lib/active_record/association_relation.rb +22 -12
  8. data/lib/active_record/associations/alias_tracker.rb +41 -30
  9. data/lib/active_record/associations/association.rb +106 -41
  10. data/lib/active_record/associations/association_scope.rb +30 -21
  11. data/lib/active_record/associations/belongs_to_association.rb +69 -14
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +20 -6
  13. data/lib/active_record/associations/builder/association.rb +39 -6
  14. data/lib/active_record/associations/builder/belongs_to.rb +47 -17
  15. data/lib/active_record/associations/builder/collection_association.rb +14 -6
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -10
  17. data/lib/active_record/associations/builder/has_many.rb +7 -3
  18. data/lib/active_record/associations/builder/has_one.rb +13 -16
  19. data/lib/active_record/associations/builder/singular_association.rb +7 -3
  20. data/lib/active_record/associations/collection_association.rb +90 -53
  21. data/lib/active_record/associations/collection_proxy.rb +54 -19
  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 +21 -1
  25. data/lib/active_record/associations/has_many_association.rb +41 -10
  26. data/lib/active_record/associations/has_many_through_association.rb +29 -12
  27. data/lib/active_record/associations/has_one_association.rb +33 -9
  28. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  29. data/lib/active_record/associations/join_dependency/join_association.rb +41 -17
  30. data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
  31. data/lib/active_record/associations/join_dependency.rb +97 -54
  32. data/lib/active_record/associations/nested_error.rb +47 -0
  33. data/lib/active_record/associations/preloader/association.rb +237 -54
  34. data/lib/active_record/associations/preloader/batch.rb +48 -0
  35. data/lib/active_record/associations/preloader/branch.rb +153 -0
  36. data/lib/active_record/associations/preloader/through_association.rb +51 -17
  37. data/lib/active_record/associations/preloader.rb +55 -121
  38. data/lib/active_record/associations/singular_association.rb +16 -4
  39. data/lib/active_record/associations/through_association.rb +26 -15
  40. data/lib/active_record/associations.rb +454 -440
  41. data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
  42. data/lib/active_record/attribute_assignment.rb +11 -14
  43. data/lib/active_record/attribute_methods/before_type_cast.rb +36 -11
  44. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  45. data/lib/active_record/attribute_methods/dirty.rb +75 -34
  46. data/lib/active_record/attribute_methods/primary_key.rb +53 -31
  47. data/lib/active_record/attribute_methods/query.rb +31 -22
  48. data/lib/active_record/attribute_methods/read.rb +16 -17
  49. data/lib/active_record/attribute_methods/serialization.rb +177 -35
  50. data/lib/active_record/attribute_methods/time_zone_conversion.rb +18 -15
  51. data/lib/active_record/attribute_methods/write.rb +16 -28
  52. data/lib/active_record/attribute_methods.rb +227 -100
  53. data/lib/active_record/attributes.rb +94 -56
  54. data/lib/active_record/autosave_association.rb +119 -73
  55. data/lib/active_record/base.rb +31 -21
  56. data/lib/active_record/callbacks.rb +168 -55
  57. data/lib/active_record/coders/column_serializer.rb +61 -0
  58. data/lib/active_record/coders/json.rb +1 -1
  59. data/lib/active_record/coders/yaml_column.rb +70 -25
  60. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +284 -0
  61. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
  62. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +79 -0
  63. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +367 -565
  64. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -57
  65. data/lib/active_record/connection_adapters/abstract/database_statements.rb +277 -89
  66. data/lib/active_record/connection_adapters/abstract/query_cache.rb +241 -69
  67. data/lib/active_record/connection_adapters/abstract/quoting.rb +122 -134
  68. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  69. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -116
  70. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +324 -72
  71. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +17 -4
  72. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +611 -211
  73. data/lib/active_record/connection_adapters/abstract/transaction.rb +425 -82
  74. data/lib/active_record/connection_adapters/abstract_adapter.rb +698 -211
  75. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +464 -239
  76. data/lib/active_record/connection_adapters/column.rb +28 -1
  77. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  78. data/lib/active_record/connection_adapters/mysql/column.rb +2 -1
  79. data/lib/active_record/connection_adapters/mysql/database_statements.rb +32 -137
  80. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  81. data/lib/active_record/connection_adapters/mysql/quoting.rb +90 -43
  82. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +41 -7
  83. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +18 -1
  84. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +13 -4
  85. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +53 -15
  86. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  87. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
  88. data/lib/active_record/connection_adapters/mysql2_adapter.rb +127 -63
  89. data/lib/active_record/connection_adapters/pool_config.rb +83 -0
  90. data/lib/active_record/connection_adapters/pool_manager.rb +57 -0
  91. data/lib/active_record/connection_adapters/postgresql/column.rb +54 -2
  92. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +127 -100
  93. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  94. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +9 -5
  95. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +10 -2
  96. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +15 -2
  97. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  98. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -15
  99. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
  101. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +5 -4
  103. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  104. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
  105. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +35 -8
  106. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  109. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
  110. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +23 -4
  111. data/lib/active_record/connection_adapters/postgresql/oid.rb +4 -0
  112. data/lib/active_record/connection_adapters/postgresql/quoting.rb +139 -106
  113. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -2
  114. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +98 -4
  115. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +176 -4
  116. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -1
  117. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +462 -118
  118. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  119. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -11
  120. data/lib/active_record/connection_adapters/postgresql_adapter.rb +585 -295
  121. data/lib/active_record/connection_adapters/schema_cache.rb +399 -60
  122. data/lib/active_record/connection_adapters/sql_type_metadata.rb +8 -0
  123. data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
  124. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +99 -48
  125. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +80 -54
  126. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +27 -1
  127. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +20 -0
  128. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
  129. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +102 -24
  130. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +425 -174
  131. data/lib/active_record/connection_adapters/statement_pool.rb +7 -1
  132. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
  133. data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
  134. data/lib/active_record/connection_adapters.rb +176 -0
  135. data/lib/active_record/connection_handling.rb +243 -115
  136. data/lib/active_record/core.rb +481 -199
  137. data/lib/active_record/counter_cache.rb +69 -32
  138. data/lib/active_record/database_configurations/connection_url_resolver.rb +107 -0
  139. data/lib/active_record/database_configurations/database_config.rb +77 -10
  140. data/lib/active_record/database_configurations/hash_config.rb +148 -26
  141. data/lib/active_record/database_configurations/url_config.rb +44 -45
  142. data/lib/active_record/database_configurations.rb +190 -114
  143. data/lib/active_record/delegated_type.rb +279 -0
  144. data/lib/active_record/deprecator.rb +7 -0
  145. data/lib/active_record/destroy_association_async_job.rb +38 -0
  146. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  147. data/lib/active_record/dynamic_matchers.rb +5 -6
  148. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  149. data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
  150. data/lib/active_record/encryption/cipher.rb +53 -0
  151. data/lib/active_record/encryption/config.rb +68 -0
  152. data/lib/active_record/encryption/configurable.rb +60 -0
  153. data/lib/active_record/encryption/context.rb +42 -0
  154. data/lib/active_record/encryption/contexts.rb +76 -0
  155. data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
  156. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  157. data/lib/active_record/encryption/encryptable_record.rb +230 -0
  158. data/lib/active_record/encryption/encrypted_attribute_type.rb +175 -0
  159. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  160. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  161. data/lib/active_record/encryption/encryptor.rb +171 -0
  162. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  163. data/lib/active_record/encryption/errors.rb +15 -0
  164. data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
  165. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  166. data/lib/active_record/encryption/key.rb +28 -0
  167. data/lib/active_record/encryption/key_generator.rb +53 -0
  168. data/lib/active_record/encryption/key_provider.rb +46 -0
  169. data/lib/active_record/encryption/message.rb +33 -0
  170. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  171. data/lib/active_record/encryption/message_serializer.rb +96 -0
  172. data/lib/active_record/encryption/null_encryptor.rb +25 -0
  173. data/lib/active_record/encryption/properties.rb +76 -0
  174. data/lib/active_record/encryption/read_only_null_encryptor.rb +28 -0
  175. data/lib/active_record/encryption/scheme.rb +100 -0
  176. data/lib/active_record/encryption.rb +58 -0
  177. data/lib/active_record/enum.rb +224 -73
  178. data/lib/active_record/errors.rb +254 -36
  179. data/lib/active_record/explain.rb +30 -17
  180. data/lib/active_record/explain_registry.rb +11 -6
  181. data/lib/active_record/explain_subscriber.rb +2 -2
  182. data/lib/active_record/fixture_set/file.rb +22 -15
  183. data/lib/active_record/fixture_set/model_metadata.rb +15 -6
  184. data/lib/active_record/fixture_set/render_context.rb +3 -1
  185. data/lib/active_record/fixture_set/table_row.rb +88 -16
  186. data/lib/active_record/fixture_set/table_rows.rb +4 -5
  187. data/lib/active_record/fixtures.rb +229 -116
  188. data/lib/active_record/future_result.rb +178 -0
  189. data/lib/active_record/gem_version.rb +4 -4
  190. data/lib/active_record/inheritance.rb +121 -48
  191. data/lib/active_record/insert_all.rb +178 -29
  192. data/lib/active_record/integration.rb +16 -14
  193. data/lib/active_record/internal_metadata.rb +132 -21
  194. data/lib/active_record/legacy_yaml_adapter.rb +3 -36
  195. data/lib/active_record/locking/optimistic.rb +64 -33
  196. data/lib/active_record/locking/pessimistic.rb +21 -8
  197. data/lib/active_record/log_subscriber.rb +61 -30
  198. data/lib/active_record/marshalling.rb +59 -0
  199. data/lib/active_record/message_pack.rb +124 -0
  200. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  201. data/lib/active_record/middleware/database_selector/resolver.rb +19 -19
  202. data/lib/active_record/middleware/database_selector.rb +25 -13
  203. data/lib/active_record/middleware/shard_selector.rb +62 -0
  204. data/lib/active_record/migration/command_recorder.rb +160 -55
  205. data/lib/active_record/migration/compatibility.rb +286 -43
  206. data/lib/active_record/migration/default_strategy.rb +22 -0
  207. data/lib/active_record/migration/execution_strategy.rb +19 -0
  208. data/lib/active_record/migration/join_table.rb +1 -2
  209. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  210. data/lib/active_record/migration.rb +421 -193
  211. data/lib/active_record/model_schema.rb +217 -125
  212. data/lib/active_record/nested_attributes.rb +62 -27
  213. data/lib/active_record/no_touching.rb +4 -4
  214. data/lib/active_record/normalization.rb +163 -0
  215. data/lib/active_record/persistence.rb +322 -319
  216. data/lib/active_record/promise.rb +84 -0
  217. data/lib/active_record/query_cache.rb +18 -15
  218. data/lib/active_record/query_logs.rb +193 -0
  219. data/lib/active_record/query_logs_formatter.rb +41 -0
  220. data/lib/active_record/querying.rb +54 -14
  221. data/lib/active_record/railtie.rb +250 -72
  222. data/lib/active_record/railties/console_sandbox.rb +2 -4
  223. data/lib/active_record/railties/controller_runtime.rb +25 -11
  224. data/lib/active_record/railties/databases.rake +312 -197
  225. data/lib/active_record/railties/job_runtime.rb +23 -0
  226. data/lib/active_record/readonly_attributes.rb +45 -3
  227. data/lib/active_record/reflection.rb +389 -146
  228. data/lib/active_record/relation/batches/batch_enumerator.rb +61 -16
  229. data/lib/active_record/relation/batches.rb +214 -73
  230. data/lib/active_record/relation/calculations.rb +379 -124
  231. data/lib/active_record/relation/delegation.rb +36 -23
  232. data/lib/active_record/relation/finder_methods.rb +159 -49
  233. data/lib/active_record/relation/from_clause.rb +5 -1
  234. data/lib/active_record/relation/merger.rb +41 -33
  235. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -11
  236. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -7
  237. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +20 -13
  238. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  239. data/lib/active_record/relation/predicate_builder.rb +79 -53
  240. data/lib/active_record/relation/query_attribute.rb +30 -12
  241. data/lib/active_record/relation/query_methods.rb +1156 -279
  242. data/lib/active_record/relation/record_fetch_warning.rb +12 -11
  243. data/lib/active_record/relation/spawn_methods.rb +10 -9
  244. data/lib/active_record/relation/where_clause.rb +100 -66
  245. data/lib/active_record/relation.rb +829 -194
  246. data/lib/active_record/result.rb +76 -56
  247. data/lib/active_record/runtime_registry.rb +71 -13
  248. data/lib/active_record/sanitization.rb +86 -47
  249. data/lib/active_record/schema.rb +39 -23
  250. data/lib/active_record/schema_dumper.rb +140 -33
  251. data/lib/active_record/schema_migration.rb +74 -29
  252. data/lib/active_record/scoping/default.rb +73 -19
  253. data/lib/active_record/scoping/named.rb +10 -28
  254. data/lib/active_record/scoping.rb +65 -35
  255. data/lib/active_record/secure_password.rb +60 -0
  256. data/lib/active_record/secure_token.rb +34 -8
  257. data/lib/active_record/serialization.rb +11 -4
  258. data/lib/active_record/signed_id.rb +138 -0
  259. data/lib/active_record/statement_cache.rb +26 -10
  260. data/lib/active_record/store.rb +19 -14
  261. data/lib/active_record/suppressor.rb +15 -17
  262. data/lib/active_record/table_metadata.rb +46 -36
  263. data/lib/active_record/tasks/database_tasks.rb +371 -205
  264. data/lib/active_record/tasks/mysql_database_tasks.rb +43 -36
  265. data/lib/active_record/tasks/postgresql_database_tasks.rb +54 -41
  266. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -13
  267. data/lib/active_record/test_databases.rb +5 -4
  268. data/lib/active_record/test_fixtures.rb +189 -104
  269. data/lib/active_record/testing/query_assertions.rb +121 -0
  270. data/lib/active_record/timestamp.rb +35 -25
  271. data/lib/active_record/token_for.rb +123 -0
  272. data/lib/active_record/touch_later.rb +31 -27
  273. data/lib/active_record/transaction.rb +132 -0
  274. data/lib/active_record/transactions.rb +131 -99
  275. data/lib/active_record/translation.rb +3 -5
  276. data/lib/active_record/type/adapter_specific_registry.rb +33 -18
  277. data/lib/active_record/type/hash_lookup_type_map.rb +34 -2
  278. data/lib/active_record/type/internal/timezone.rb +7 -2
  279. data/lib/active_record/type/serialized.rb +11 -6
  280. data/lib/active_record/type/time.rb +14 -0
  281. data/lib/active_record/type/type_map.rb +17 -21
  282. data/lib/active_record/type/unsigned_integer.rb +0 -1
  283. data/lib/active_record/type.rb +7 -2
  284. data/lib/active_record/type_caster/connection.rb +4 -5
  285. data/lib/active_record/type_caster/map.rb +8 -5
  286. data/lib/active_record/validations/absence.rb +1 -1
  287. data/lib/active_record/validations/associated.rb +13 -8
  288. data/lib/active_record/validations/numericality.rb +36 -0
  289. data/lib/active_record/validations/presence.rb +5 -28
  290. data/lib/active_record/validations/uniqueness.rb +88 -18
  291. data/lib/active_record/validations.rb +15 -8
  292. data/lib/active_record/version.rb +1 -1
  293. data/lib/active_record.rb +446 -40
  294. data/lib/arel/alias_predication.rb +1 -1
  295. data/lib/arel/attributes/attribute.rb +4 -8
  296. data/lib/arel/collectors/bind.rb +8 -1
  297. data/lib/arel/collectors/composite.rb +15 -0
  298. data/lib/arel/collectors/sql_string.rb +7 -0
  299. data/lib/arel/collectors/substitute_binds.rb +7 -0
  300. data/lib/arel/crud.rb +30 -22
  301. data/lib/arel/delete_manager.rb +23 -4
  302. data/lib/arel/errors.rb +10 -0
  303. data/lib/arel/factory_methods.rb +4 -0
  304. data/lib/arel/filter_predications.rb +9 -0
  305. data/lib/arel/insert_manager.rb +2 -3
  306. data/lib/arel/nodes/binary.rb +82 -9
  307. data/lib/arel/nodes/bind_param.rb +8 -0
  308. data/lib/arel/nodes/bound_sql_literal.rb +65 -0
  309. data/lib/arel/nodes/casted.rb +22 -10
  310. data/lib/arel/nodes/cte.rb +36 -0
  311. data/lib/arel/nodes/delete_statement.rb +14 -13
  312. data/lib/arel/nodes/equality.rb +6 -9
  313. data/lib/arel/nodes/filter.rb +10 -0
  314. data/lib/arel/nodes/fragments.rb +35 -0
  315. data/lib/arel/nodes/function.rb +1 -0
  316. data/lib/arel/nodes/grouping.rb +3 -0
  317. data/lib/arel/nodes/homogeneous_in.rb +68 -0
  318. data/lib/arel/nodes/in.rb +8 -1
  319. data/lib/arel/nodes/infix_operation.rb +13 -1
  320. data/lib/arel/nodes/insert_statement.rb +2 -2
  321. data/lib/arel/nodes/join_source.rb +1 -1
  322. data/lib/arel/nodes/leading_join.rb +8 -0
  323. data/lib/arel/nodes/{and.rb → nary.rb} +9 -2
  324. data/lib/arel/nodes/node.rb +122 -11
  325. data/lib/arel/nodes/ordering.rb +27 -0
  326. data/lib/arel/nodes/select_core.rb +2 -2
  327. data/lib/arel/nodes/select_statement.rb +2 -2
  328. data/lib/arel/nodes/sql_literal.rb +16 -0
  329. data/lib/arel/nodes/table_alias.rb +11 -3
  330. data/lib/arel/nodes/unary.rb +0 -1
  331. data/lib/arel/nodes/update_statement.rb +11 -4
  332. data/lib/arel/nodes.rb +10 -3
  333. data/lib/arel/predications.rb +31 -28
  334. data/lib/arel/select_manager.rb +18 -9
  335. data/lib/arel/table.rb +21 -10
  336. data/lib/arel/tree_manager.rb +8 -15
  337. data/lib/arel/update_manager.rb +25 -5
  338. data/lib/arel/visitors/dot.rb +94 -90
  339. data/lib/arel/visitors/mysql.rb +34 -6
  340. data/lib/arel/visitors/postgresql.rb +5 -16
  341. data/lib/arel/visitors/sqlite.rb +25 -1
  342. data/lib/arel/visitors/to_sql.rb +227 -81
  343. data/lib/arel/visitors/visitor.rb +2 -3
  344. data/lib/arel/visitors.rb +0 -7
  345. data/lib/arel.rb +37 -15
  346. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  347. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  348. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  349. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  350. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +6 -1
  351. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
  352. data/lib/rails/generators/active_record/migration.rb +9 -3
  353. data/lib/rails/generators/active_record/model/USAGE +113 -0
  354. data/lib/rails/generators/active_record/model/model_generator.rb +49 -4
  355. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  356. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  357. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  358. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  359. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  360. metadata +117 -30
  361. data/lib/active_record/attribute_decorators.rb +0 -90
  362. data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
  363. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  364. data/lib/active_record/define_callbacks.rb +0 -22
  365. data/lib/active_record/null_relation.rb +0 -68
  366. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  367. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  368. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  369. data/lib/arel/attributes.rb +0 -22
  370. data/lib/arel/visitors/depth_first.rb +0 -204
  371. data/lib/arel/visitors/ibm_db.rb +0 -34
  372. data/lib/arel/visitors/informix.rb +0 -62
  373. data/lib/arel/visitors/mssql.rb +0 -157
  374. data/lib/arel/visitors/oracle.rb +0 -159
  375. data/lib/arel/visitors/oracle12.rb +0 -66
  376. data/lib/arel/visitors/where_sql.rb +0 -23
@@ -4,19 +4,18 @@ module ActiveRecord
4
4
  # See ActiveRecord::Transactions::ClassMethods for documentation.
5
5
  module Transactions
6
6
  extend ActiveSupport::Concern
7
- #:nodoc:
7
+ # :nodoc:
8
8
  ACTIONS = [:create, :destroy, :update]
9
9
 
10
10
  included do
11
11
  define_callbacks :commit, :rollback,
12
12
  :before_commit,
13
- :before_commit_without_transaction_enrollment,
14
- :commit_without_transaction_enrollment,
15
- :rollback_without_transaction_enrollment,
16
13
  scope: [:kind, :name]
17
14
  end
18
15
 
19
- # = Active Record Transactions
16
+ attr_accessor :_new_record_before_last_commit, :_last_transaction_return_status # :nodoc:
17
+
18
+ # = Active Record \Transactions
20
19
  #
21
20
  # \Transactions are protective blocks where SQL statements are only permanent
22
21
  # if they can all succeed as one atomic action. The classic example is a
@@ -101,7 +100,8 @@ module ActiveRecord
101
100
  # catch those in your application code.
102
101
  #
103
102
  # One exception is the ActiveRecord::Rollback exception, which will trigger
104
- # a ROLLBACK when raised, but not be re-raised by the transaction block.
103
+ # a ROLLBACK when raised, but not be re-raised by the transaction block. Any
104
+ # other exception will be re-raised.
105
105
  #
106
106
  # *Warning*: one should not catch ActiveRecord::StatementInvalid exceptions
107
107
  # inside a transaction block. ActiveRecord::StatementInvalid exceptions indicate that an
@@ -164,13 +164,13 @@ module ActiveRecord
164
164
  # end
165
165
  # end
166
166
  #
167
- # only "Kotori" is created. This works on MySQL and PostgreSQL. SQLite3 version >= '3.6.8' also supports it.
167
+ # only "Kotori" is created.
168
168
  #
169
169
  # Most databases don't support true nested transactions. At the time of
170
170
  # writing, the only database that we're aware of that supports true nested
171
171
  # transactions, is MS-SQL. Because of this, Active Record emulates nested
172
- # transactions by using savepoints on MySQL and PostgreSQL. See
173
- # https://dev.mysql.com/doc/refman/5.7/en/savepoint.html
172
+ # transactions by using savepoints. See
173
+ # https://dev.mysql.com/doc/refman/en/savepoint.html
174
174
  # for more information about savepoints.
175
175
  #
176
176
  # === \Callbacks
@@ -188,6 +188,27 @@ module ActiveRecord
188
188
  # #after_commit is a good spot to put in a hook to clearing a cache since clearing it from
189
189
  # within a transaction could trigger the cache to be regenerated before the database is updated.
190
190
  #
191
+ # ==== NOTE: Callbacks are deduplicated per callback by filter.
192
+ #
193
+ # Trying to define multiple callbacks with the same filter will result in a single callback being run.
194
+ #
195
+ # For example:
196
+ #
197
+ # after_commit :do_something
198
+ # after_commit :do_something # only the last one will be called
199
+ #
200
+ # This applies to all variations of <tt>after_*_commit</tt> callbacks as well.
201
+ #
202
+ # after_commit :do_something
203
+ # after_create_commit :do_something
204
+ # after_save_commit :do_something
205
+ #
206
+ # It is recommended to use the +on:+ option to specify when the callback should be run.
207
+ #
208
+ # after_commit :do_something, on: [:create, :update]
209
+ #
210
+ # This is equivalent to using +after_create_commit+ and +after_update_commit+, but will not be deduplicated.
211
+ #
191
212
  # === Caveats
192
213
  #
193
214
  # If you're on MySQL, then do not use Data Definition Language (DDL) operations in nested
@@ -198,9 +219,9 @@ module ActiveRecord
198
219
  # database error will occur because the savepoint has already been
199
220
  # automatically released. The following example demonstrates the problem:
200
221
  #
201
- # Model.connection.transaction do # BEGIN
202
- # Model.connection.transaction(requires_new: true) do # CREATE SAVEPOINT active_record_1
203
- # Model.connection.create_table(...) # active_record_1 now automatically released
222
+ # Model.lease_connection.transaction do # BEGIN
223
+ # Model.lease_connection.transaction(requires_new: true) do # CREATE SAVEPOINT active_record_1
224
+ # Model.lease_connection.create_table(...) # active_record_1 now automatically released
204
225
  # end # RELEASE SAVEPOINT active_record_1
205
226
  # # ^^^^ BOOM! database error!
206
227
  # end
@@ -208,8 +229,21 @@ module ActiveRecord
208
229
  # Note that "TRUNCATE" is also a MySQL DDL statement!
209
230
  module ClassMethods
210
231
  # See the ConnectionAdapters::DatabaseStatements#transaction API docs.
211
- def transaction(options = {}, &block)
212
- connection.transaction(options, &block)
232
+ def transaction(**options, &block)
233
+ with_connection do |connection|
234
+ connection.transaction(**options, &block)
235
+ end
236
+ end
237
+
238
+ # Returns a representation of the current transaction state,
239
+ # which can be a top level transaction, a savepoint, or the absence of a transaction.
240
+ #
241
+ # An object is always returned, whether or not a transaction is currently active.
242
+ # To check if a transaction was opened, use <tt>current_transaction.open?</tt>.
243
+ #
244
+ # See the ActiveRecord::Transaction documentation for detailed behavior.
245
+ def current_transaction
246
+ connection_pool.active_connection&.current_transaction&.user_transaction || Transaction::NULL_TRANSACTION
213
247
  end
214
248
 
215
249
  def before_commit(*args, &block) # :nodoc:
@@ -230,31 +264,31 @@ module ActiveRecord
230
264
  # after_commit :do_bar_baz, on: [:update, :destroy]
231
265
  #
232
266
  def after_commit(*args, &block)
233
- set_options_for_callbacks!(args)
267
+ set_options_for_callbacks!(args, prepend_option)
234
268
  set_callback(:commit, :after, *args, &block)
235
269
  end
236
270
 
237
271
  # Shortcut for <tt>after_commit :hook, on: [ :create, :update ]</tt>.
238
272
  def after_save_commit(*args, &block)
239
- set_options_for_callbacks!(args, on: [ :create, :update ])
273
+ set_options_for_callbacks!(args, on: [ :create, :update ], **prepend_option)
240
274
  set_callback(:commit, :after, *args, &block)
241
275
  end
242
276
 
243
277
  # Shortcut for <tt>after_commit :hook, on: :create</tt>.
244
278
  def after_create_commit(*args, &block)
245
- set_options_for_callbacks!(args, on: :create)
279
+ set_options_for_callbacks!(args, on: :create, **prepend_option)
246
280
  set_callback(:commit, :after, *args, &block)
247
281
  end
248
282
 
249
283
  # Shortcut for <tt>after_commit :hook, on: :update</tt>.
250
284
  def after_update_commit(*args, &block)
251
- set_options_for_callbacks!(args, on: :update)
285
+ set_options_for_callbacks!(args, on: :update, **prepend_option)
252
286
  set_callback(:commit, :after, *args, &block)
253
287
  end
254
288
 
255
289
  # Shortcut for <tt>after_commit :hook, on: :destroy</tt>.
256
290
  def after_destroy_commit(*args, &block)
257
- set_options_for_callbacks!(args, on: :destroy)
291
+ set_options_for_callbacks!(args, on: :destroy, **prepend_option)
258
292
  set_callback(:commit, :after, *args, &block)
259
293
  end
260
294
 
@@ -262,26 +296,37 @@ module ActiveRecord
262
296
  #
263
297
  # Please check the documentation of #after_commit for options.
264
298
  def after_rollback(*args, &block)
265
- set_options_for_callbacks!(args)
299
+ set_options_for_callbacks!(args, prepend_option)
266
300
  set_callback(:rollback, :after, *args, &block)
267
301
  end
268
302
 
269
- def before_commit_without_transaction_enrollment(*args, &block) # :nodoc:
270
- set_options_for_callbacks!(args)
271
- set_callback(:before_commit_without_transaction_enrollment, :before, *args, &block)
272
- end
303
+ # Similar to ActiveSupport::Callbacks::ClassMethods#set_callback, but with
304
+ # support for options available on #after_commit and #after_rollback callbacks.
305
+ def set_callback(name, *filter_list, &block)
306
+ options = filter_list.extract_options!
307
+ filter_list << options
308
+
309
+ if name.in?([:commit, :rollback]) && options[:on]
310
+ fire_on = Array(options[:on])
311
+ assert_valid_transaction_action(fire_on)
312
+ options[:if] = [
313
+ -> { transaction_include_any_action?(fire_on) },
314
+ *options[:if]
315
+ ]
316
+ end
273
317
 
274
- def after_commit_without_transaction_enrollment(*args, &block) # :nodoc:
275
- set_options_for_callbacks!(args)
276
- set_callback(:commit_without_transaction_enrollment, :after, *args, &block)
277
- end
278
318
 
279
- def after_rollback_without_transaction_enrollment(*args, &block) # :nodoc:
280
- set_options_for_callbacks!(args)
281
- set_callback(:rollback_without_transaction_enrollment, :after, *args, &block)
319
+ super(name, *filter_list, &block)
282
320
  end
283
321
 
284
322
  private
323
+ def prepend_option
324
+ if ActiveRecord.run_after_transaction_callbacks_in_order_defined
325
+ { prepend: true }
326
+ else
327
+ {}
328
+ end
329
+ end
285
330
 
286
331
  def set_options_for_callbacks!(args, enforced_options = {})
287
332
  options = args.extract_options!.merge!(enforced_options)
@@ -290,8 +335,10 @@ module ActiveRecord
290
335
  if options[:on]
291
336
  fire_on = Array(options[:on])
292
337
  assert_valid_transaction_action(fire_on)
293
- options[:if] = Array(options[:if])
294
- options[:if].unshift(-> { transaction_include_any_action?(fire_on) })
338
+ options[:if] = [
339
+ -> { transaction_include_any_action?(fire_on) },
340
+ *options[:if]
341
+ ]
295
342
  end
296
343
  end
297
344
 
@@ -303,28 +350,27 @@ module ActiveRecord
303
350
  end
304
351
 
305
352
  # See ActiveRecord::Transactions::ClassMethods for detailed documentation.
306
- def transaction(options = {}, &block)
307
- self.class.transaction(options, &block)
353
+ def transaction(**options, &block)
354
+ self.class.transaction(**options, &block)
308
355
  end
309
356
 
310
- def destroy #:nodoc:
357
+ def destroy # :nodoc:
311
358
  with_transaction_returning_status { super }
312
359
  end
313
360
 
314
- def save(*) #:nodoc:
361
+ def save(**) # :nodoc:
315
362
  with_transaction_returning_status { super }
316
363
  end
317
364
 
318
- def save!(*) #:nodoc:
365
+ def save!(**) # :nodoc:
319
366
  with_transaction_returning_status { super }
320
367
  end
321
368
 
322
- def touch(*) #:nodoc:
369
+ def touch(*, **) # :nodoc:
323
370
  with_transaction_returning_status { super }
324
371
  end
325
372
 
326
373
  def before_committed! # :nodoc:
327
- _run_before_commit_without_transaction_enrollment_callbacks
328
374
  _run_before_commit_callbacks
329
375
  end
330
376
 
@@ -332,50 +378,49 @@ module ActiveRecord
332
378
  #
333
379
  # Ensure that it is not called if the object was never persisted (failed create),
334
380
  # but call it after the commit of a destroyed object.
335
- def committed!(should_run_callbacks: true) #:nodoc:
381
+ def committed!(should_run_callbacks: true) # :nodoc:
382
+ @_start_transaction_state = nil
336
383
  if should_run_callbacks
337
384
  @_committed_already_called = true
338
- _run_commit_without_transaction_enrollment_callbacks
339
385
  _run_commit_callbacks
340
386
  end
341
387
  ensure
342
- @_committed_already_called = false
343
- force_clear_transaction_record_state
388
+ @_committed_already_called = @_trigger_update_callback = @_trigger_destroy_callback = false
344
389
  end
345
390
 
346
391
  # Call the #after_rollback callbacks. The +force_restore_state+ argument indicates if the record
347
392
  # state should be rolled back to the beginning or just to the last savepoint.
348
- def rolledback!(force_restore_state: false, should_run_callbacks: true) #:nodoc:
393
+ def rolledback!(force_restore_state: false, should_run_callbacks: true) # :nodoc:
349
394
  if should_run_callbacks
350
395
  _run_rollback_callbacks
351
- _run_rollback_without_transaction_enrollment_callbacks
352
396
  end
353
397
  ensure
354
398
  restore_transaction_record_state(force_restore_state)
355
399
  clear_transaction_record_state
400
+ @_trigger_update_callback = @_trigger_destroy_callback = false if force_restore_state
356
401
  end
357
402
 
358
- # Executes +method+ within a transaction and captures its return value as a
359
- # status flag. If the status is true the transaction is committed, otherwise
360
- # a ROLLBACK is issued. In any case the status flag is returned.
403
+ # Executes a block within a transaction and captures its return value as a
404
+ # status flag. If the status is true, the transaction is committed,
405
+ # otherwise a ROLLBACK is issued. In any case, the status flag is returned.
361
406
  #
362
407
  # This method is available within the context of an ActiveRecord::Base
363
408
  # instance.
364
409
  def with_transaction_returning_status
365
- status = nil
366
- self.class.transaction do
367
- if has_transactional_callbacks?
368
- add_to_transaction
369
- else
370
- sync_with_transaction_state if @transaction_state&.finalized?
371
- @transaction_state = self.class.connection.transaction_state
372
- end
373
- remember_transaction_record_state
410
+ self.class.with_connection do |connection|
411
+ status = nil
412
+ ensure_finalize = !connection.transaction_open?
374
413
 
375
- status = yield
376
- raise ActiveRecord::Rollback unless status
414
+ connection.transaction do
415
+ add_to_transaction(ensure_finalize || has_transactional_callbacks?)
416
+ remember_transaction_record_state
417
+
418
+ status = yield
419
+ raise ActiveRecord::Rollback unless status
420
+ end
421
+ @_last_transaction_return_status = status
422
+ status
377
423
  end
378
- status
379
424
  end
380
425
 
381
426
  def trigger_transactional_callbacks? # :nodoc:
@@ -386,11 +431,20 @@ module ActiveRecord
386
431
  private
387
432
  attr_reader :_committed_already_called, :_trigger_update_callback, :_trigger_destroy_callback
388
433
 
434
+ def init_internals
435
+ super
436
+ @_start_transaction_state = nil
437
+ @_last_transaction_return_status = nil
438
+ @_committed_already_called = nil
439
+ @_new_record_before_last_commit = nil
440
+ end
441
+
389
442
  # Save the new record state and id of a record so it can be restored later if a transaction fails.
390
443
  def remember_transaction_record_state
391
444
  @_start_transaction_state ||= {
392
445
  id: id,
393
446
  new_record: @new_record,
447
+ previously_new_record: @previously_new_record,
394
448
  destroyed: @destroyed,
395
449
  attributes: @attributes,
396
450
  frozen?: frozen?,
@@ -409,13 +463,7 @@ module ActiveRecord
409
463
  def clear_transaction_record_state
410
464
  return unless @_start_transaction_state
411
465
  @_start_transaction_state[:level] -= 1
412
- force_clear_transaction_record_state if @_start_transaction_state[:level] < 1
413
- end
414
-
415
- # Force to clear the transaction record state.
416
- def force_clear_transaction_record_state
417
- @_start_transaction_state = nil
418
- @transaction_state = nil
466
+ @_start_transaction_state = nil if @_start_transaction_state[:level] < 1
419
467
  end
420
468
 
421
469
  # Restore the new record state and id of a record that was previously saved by a call to save_record_state.
@@ -423,6 +471,7 @@ module ActiveRecord
423
471
  if restore_state = @_start_transaction_state
424
472
  if force_restore_state || restore_state[:level] <= 1
425
473
  @new_record = restore_state[:new_record]
474
+ @previously_new_record = restore_state[:previously_new_record]
426
475
  @destroyed = restore_state[:destroyed]
427
476
  @attributes = restore_state[:attributes].map do |attr|
428
477
  value = @attributes.fetch_value(attr.name)
@@ -431,8 +480,16 @@ module ActiveRecord
431
480
  end
432
481
  @mutations_from_database = nil
433
482
  @mutations_before_last_save = nil
434
- if @attributes.fetch_value(@primary_key) != restore_state[:id]
435
- @attributes.write_from_user(@primary_key, restore_state[:id])
483
+ if self.class.composite_primary_key?
484
+ if restore_state[:id] != @primary_key.map { |col| @attributes.fetch_value(col) }
485
+ @primary_key.zip(restore_state[:id]).each do |col, val|
486
+ @attributes.write_from_user(col, val)
487
+ end
488
+ end
489
+ else
490
+ if @attributes.fetch_value(@primary_key) != restore_state[:id]
491
+ @attributes.write_from_user(@primary_key, restore_state[:id])
492
+ end
436
493
  end
437
494
  freeze if restore_state[:frozen?]
438
495
  end
@@ -455,39 +512,14 @@ module ActiveRecord
455
512
 
456
513
  # Add the record to the current transaction so that the #after_rollback and #after_commit
457
514
  # callbacks can be called.
458
- def add_to_transaction
459
- self.class.connection.add_transaction_record(self)
515
+ def add_to_transaction(ensure_finalize = true)
516
+ self.class.with_connection do |connection|
517
+ connection.add_transaction_record(self, ensure_finalize)
518
+ end
460
519
  end
461
520
 
462
521
  def has_transactional_callbacks?
463
522
  !_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_before_commit_callbacks.empty?
464
523
  end
465
-
466
- # Updates the attributes on this particular Active Record object so that
467
- # if it's associated with a transaction, then the state of the Active Record
468
- # object will be updated to reflect the current state of the transaction.
469
- #
470
- # The <tt>@transaction_state</tt> variable stores the states of the associated
471
- # transaction. This relies on the fact that a transaction can only be in
472
- # one rollback or commit (otherwise a list of states would be required).
473
- # Each Active Record object inside of a transaction carries that transaction's
474
- # TransactionState.
475
- #
476
- # This method checks to see if the ActiveRecord object's state reflects
477
- # the TransactionState, and rolls back or commits the Active Record object
478
- # as appropriate.
479
- def sync_with_transaction_state
480
- if transaction_state = @transaction_state
481
- if transaction_state.fully_committed?
482
- force_clear_transaction_record_state
483
- elsif transaction_state.committed?
484
- clear_transaction_record_state
485
- elsif transaction_state.rolledback?
486
- force_restore_state = transaction_state.fully_rolledback?
487
- restore_transaction_record_state(force_restore_state)
488
- clear_transaction_record_state
489
- end
490
- end
491
- end
492
524
  end
493
525
  end
@@ -2,10 +2,8 @@
2
2
 
3
3
  module ActiveRecord
4
4
  module Translation
5
- include ActiveModel::Translation
6
-
7
5
  # Set the lookup ancestors for ActiveModel.
8
- def lookup_ancestors #:nodoc:
6
+ def lookup_ancestors # :nodoc:
9
7
  klass = self
10
8
  classes = [klass]
11
9
  return classes if klass == ActiveRecord::Base
@@ -16,8 +14,8 @@ module ActiveRecord
16
14
  classes
17
15
  end
18
16
 
19
- # Set the i18n scope to overwrite ActiveModel.
20
- def i18n_scope #:nodoc:
17
+ # Set the i18n scope to override ActiveModel.
18
+ def i18n_scope # :nodoc:
21
19
  :activerecord
22
20
  end
23
21
  end
@@ -1,29 +1,50 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_model/type/registry"
4
-
5
3
  module ActiveRecord
6
4
  # :stopdoc:
7
5
  module Type
8
- class AdapterSpecificRegistry < ActiveModel::Type::Registry
6
+ class AdapterSpecificRegistry # :nodoc:
7
+ def initialize
8
+ @registrations = []
9
+ end
10
+
11
+ def initialize_copy(other)
12
+ @registrations = @registrations.dup
13
+ end
14
+
9
15
  def add_modifier(options, klass, **args)
10
16
  registrations << DecorationRegistration.new(options, klass, **args)
11
17
  end
12
18
 
13
- private
19
+ def register(type_name, klass = nil, **options, &block)
20
+ unless block_given?
21
+ block = proc { |_, *args| klass.new(*args) }
22
+ block.ruby2_keywords if block.respond_to?(:ruby2_keywords)
23
+ end
24
+ registrations << Registration.new(type_name, block, **options)
25
+ end
26
+
27
+ def lookup(symbol, *args, **kwargs)
28
+ registration = find_registration(symbol, *args, **kwargs)
14
29
 
15
- def registration_klass
16
- Registration
30
+ if registration
31
+ registration.call(self, symbol, *args, **kwargs)
32
+ else
33
+ raise ArgumentError, "Unknown type #{symbol.inspect}"
17
34
  end
35
+ end
36
+
37
+ private
38
+ attr_reader :registrations
18
39
 
19
- def find_registration(symbol, *args)
40
+ def find_registration(symbol, *args, **kwargs)
20
41
  registrations
21
- .select { |registration| registration.matches?(symbol, *args) }
42
+ .select { |registration| registration.matches?(symbol, *args, **kwargs) }
22
43
  .max
23
44
  end
24
45
  end
25
46
 
26
- class Registration
47
+ class Registration # :nodoc:
27
48
  def initialize(name, block, adapter: nil, override: nil)
28
49
  @name = name
29
50
  @block = block
@@ -32,11 +53,7 @@ module ActiveRecord
32
53
  end
33
54
 
34
55
  def call(_registry, *args, adapter: nil, **kwargs)
35
- if kwargs.any? # https://bugs.ruby-lang.org/issues/10856
36
- block.call(*args, **kwargs)
37
- else
38
- block.call(*args)
39
- end
56
+ block.call(*args, **kwargs)
40
57
  end
41
58
 
42
59
  def matches?(type_name, *args, **kwargs)
@@ -53,7 +70,6 @@ module ActiveRecord
53
70
  end
54
71
 
55
72
  protected
56
-
57
73
  attr_reader :name, :block, :adapter, :override
58
74
 
59
75
  def priority
@@ -72,7 +88,6 @@ module ActiveRecord
72
88
  end
73
89
 
74
90
  private
75
-
76
91
  def matches_adapter?(adapter: nil, **)
77
92
  (self.adapter.nil? || adapter == self.adapter)
78
93
  end
@@ -92,7 +107,7 @@ module ActiveRecord
92
107
  end
93
108
  end
94
109
 
95
- class DecorationRegistration < Registration
110
+ class DecorationRegistration < Registration # :nodoc:
96
111
  def initialize(options, klass, adapter: nil)
97
112
  @options = options
98
113
  @klass = klass
@@ -123,7 +138,7 @@ module ActiveRecord
123
138
  end
124
139
  end
125
140
 
126
- class TypeConflictError < StandardError
141
+ class TypeConflictError < StandardError # :nodoc:
127
142
  end
128
143
  # :startdoc:
129
144
  end
@@ -2,7 +2,40 @@
2
2
 
3
3
  module ActiveRecord
4
4
  module Type
5
- class HashLookupTypeMap < TypeMap # :nodoc:
5
+ class HashLookupTypeMap # :nodoc:
6
+ def initialize(parent = nil)
7
+ @mapping = {}
8
+ @cache = Concurrent::Map.new do |h, key|
9
+ h.fetch_or_store(key, Concurrent::Map.new)
10
+ end
11
+ end
12
+
13
+ def lookup(lookup_key, *args)
14
+ fetch(lookup_key, *args) { Type.default_value }
15
+ end
16
+
17
+ def fetch(lookup_key, *args, &block)
18
+ @cache[lookup_key].fetch_or_store(args) do
19
+ perform_fetch(lookup_key, *args, &block)
20
+ end
21
+ end
22
+
23
+ def register_type(key, value = nil, &block)
24
+ raise ::ArgumentError unless value || block
25
+
26
+ if block
27
+ @mapping[key] = block
28
+ else
29
+ @mapping[key] = proc { value }
30
+ end
31
+ @cache.clear
32
+ end
33
+
34
+ def clear
35
+ @mapping.clear
36
+ @cache.clear
37
+ end
38
+
6
39
  def alias_type(type, alias_type)
7
40
  register_type(type) { |_, *args| lookup(alias_type, *args) }
8
41
  end
@@ -16,7 +49,6 @@ module ActiveRecord
16
49
  end
17
50
 
18
51
  private
19
-
20
52
  def perform_fetch(type, *args, &block)
21
53
  @mapping.fetch(type, block).call(type, *args)
22
54
  end
@@ -4,12 +4,17 @@ module ActiveRecord
4
4
  module Type
5
5
  module Internal
6
6
  module Timezone
7
+ def initialize(timezone: nil, **kwargs)
8
+ super(**kwargs)
9
+ @timezone = timezone
10
+ end
11
+
7
12
  def is_utc?
8
- ActiveRecord::Base.default_timezone == :utc
13
+ default_timezone == :utc
9
14
  end
10
15
 
11
16
  def default_timezone
12
- ActiveRecord::Base.default_timezone
17
+ @timezone || ActiveRecord.default_timezone
13
18
  end
14
19
  end
15
20
  end
@@ -30,9 +30,7 @@ module ActiveRecord
30
30
  end
31
31
  end
32
32
 
33
- def inspect
34
- Kernel.instance_method(:inspect).bind(self).call
35
- end
33
+ define_method(:inspect, Kernel.instance_method(:inspect))
36
34
 
37
35
  def changed_in_place?(raw_old_value, value)
38
36
  return false if value.nil?
@@ -55,15 +53,22 @@ module ActiveRecord
55
53
  coder.respond_to?(:object_class) && value.is_a?(coder.object_class)
56
54
  end
57
55
 
58
- private
56
+ def serialized? # :nodoc:
57
+ true
58
+ end
59
59
 
60
+ private
60
61
  def default_value?(value)
61
62
  value == coder.load(nil)
62
63
  end
63
64
 
64
65
  def encoded(value)
65
- unless default_value?(value)
66
- coder.dump(value)
66
+ return if default_value?(value)
67
+ payload = coder.dump(value)
68
+ if payload && @subtype.binary?
69
+ ActiveModel::Type::Binary::Data.new(payload)
70
+ else
71
+ payload
67
72
  end
68
73
  end
69
74
  end
@@ -16,6 +16,20 @@ module ActiveRecord
16
16
  value
17
17
  end
18
18
  end
19
+
20
+ def serialize_cast_value(value) # :nodoc:
21
+ Value.new(super) if value
22
+ end
23
+
24
+ private
25
+ def cast_value(value)
26
+ case value = super
27
+ when Value
28
+ value.__getobj__
29
+ else
30
+ value
31
+ end
32
+ end
19
33
  end
20
34
  end
21
35
  end