activerecord 4.2.9 → 6.1.4.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (374) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +964 -1382
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +15 -14
  5. data/examples/performance.rb +33 -32
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/aggregations.rb +266 -251
  8. data/lib/active_record/association_relation.rb +40 -15
  9. data/lib/active_record/associations/alias_tracker.rb +40 -43
  10. data/lib/active_record/associations/association.rb +162 -69
  11. data/lib/active_record/associations/association_scope.rb +105 -130
  12. data/lib/active_record/associations/belongs_to_association.rb +83 -65
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
  14. data/lib/active_record/associations/builder/association.rb +57 -43
  15. data/lib/active_record/associations/builder/belongs_to.rb +74 -57
  16. data/lib/active_record/associations/builder/collection_association.rb +15 -37
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +49 -66
  18. data/lib/active_record/associations/builder/has_many.rb +13 -5
  19. data/lib/active_record/associations/builder/has_one.rb +44 -6
  20. data/lib/active_record/associations/builder/singular_association.rb +16 -10
  21. data/lib/active_record/associations/collection_association.rb +148 -287
  22. data/lib/active_record/associations/collection_proxy.rb +252 -150
  23. data/lib/active_record/associations/foreign_association.rb +23 -1
  24. data/lib/active_record/associations/has_many_association.rb +56 -98
  25. data/lib/active_record/associations/has_many_through_association.rb +68 -89
  26. data/lib/active_record/associations/has_one_association.rb +73 -47
  27. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  28. data/lib/active_record/associations/join_dependency/join_association.rb +54 -81
  29. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  31. data/lib/active_record/associations/join_dependency.rb +174 -169
  32. data/lib/active_record/associations/preloader/association.rb +108 -115
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  34. data/lib/active_record/associations/preloader.rb +97 -94
  35. data/lib/active_record/associations/singular_association.rb +18 -39
  36. data/lib/active_record/associations/through_association.rb +39 -19
  37. data/lib/active_record/associations.rb +1845 -1598
  38. data/lib/active_record/attribute_assignment.rb +59 -185
  39. data/lib/active_record/attribute_methods/before_type_cast.rb +18 -10
  40. data/lib/active_record/attribute_methods/dirty.rb +168 -148
  41. data/lib/active_record/attribute_methods/primary_key.rb +93 -83
  42. data/lib/active_record/attribute_methods/query.rb +8 -10
  43. data/lib/active_record/attribute_methods/read.rb +19 -79
  44. data/lib/active_record/attribute_methods/serialization.rb +49 -24
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +55 -36
  46. data/lib/active_record/attribute_methods/write.rb +24 -55
  47. data/lib/active_record/attribute_methods.rb +149 -154
  48. data/lib/active_record/attributes.rb +234 -78
  49. data/lib/active_record/autosave_association.rb +133 -60
  50. data/lib/active_record/base.rb +46 -46
  51. data/lib/active_record/callbacks.rb +234 -79
  52. data/lib/active_record/coders/json.rb +3 -1
  53. data/lib/active_record/coders/yaml_column.rb +34 -13
  54. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -323
  55. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
  56. data/lib/active_record/connection_adapters/abstract/database_statements.rb +292 -124
  57. data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
  58. data/lib/active_record/connection_adapters/abstract/quoting.rb +177 -60
  59. data/lib/active_record/connection_adapters/abstract/savepoints.rb +8 -6
  60. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
  61. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +473 -255
  62. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  63. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +869 -286
  64. data/lib/active_record/connection_adapters/abstract/transaction.rb +257 -91
  65. data/lib/active_record/connection_adapters/abstract_adapter.rb +483 -230
  66. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +557 -640
  67. data/lib/active_record/connection_adapters/column.rb +67 -40
  68. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  69. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  70. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  71. data/lib/active_record/connection_adapters/mysql/database_statements.rb +194 -0
  72. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
  73. data/lib/active_record/connection_adapters/mysql/quoting.rb +96 -0
  74. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +97 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +103 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +91 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
  78. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
  79. data/lib/active_record/connection_adapters/mysql2_adapter.rb +80 -192
  80. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  81. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +44 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +75 -160
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -58
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +4 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +8 -6
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +14 -19
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -20
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  98. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  101. data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -5
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  109. data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -25
  110. data/lib/active_record/connection_adapters/postgresql/quoting.rb +145 -48
  111. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  112. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
  114. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
  115. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +496 -298
  116. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
  117. data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
  118. data/lib/active_record/connection_adapters/postgresql_adapter.rb +588 -375
  119. data/lib/active_record/connection_adapters/schema_cache.rb +167 -29
  120. data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
  121. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
  122. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  123. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +21 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  126. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  127. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
  128. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +322 -373
  129. data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
  130. data/lib/active_record/connection_adapters.rb +52 -0
  131. data/lib/active_record/connection_handling.rb +314 -41
  132. data/lib/active_record/core.rb +458 -241
  133. data/lib/active_record/counter_cache.rb +70 -49
  134. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  135. data/lib/active_record/database_configurations/database_config.rb +80 -0
  136. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  137. data/lib/active_record/database_configurations/url_config.rb +53 -0
  138. data/lib/active_record/database_configurations.rb +272 -0
  139. data/lib/active_record/delegated_type.rb +209 -0
  140. data/lib/active_record/destroy_association_async_job.rb +36 -0
  141. data/lib/active_record/dynamic_matchers.rb +87 -106
  142. data/lib/active_record/enum.rb +211 -92
  143. data/lib/active_record/errors.rb +224 -54
  144. data/lib/active_record/explain.rb +27 -11
  145. data/lib/active_record/explain_registry.rb +4 -2
  146. data/lib/active_record/explain_subscriber.rb +10 -5
  147. data/lib/active_record/fixture_set/file.rb +33 -14
  148. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  149. data/lib/active_record/fixture_set/render_context.rb +17 -0
  150. data/lib/active_record/fixture_set/table_row.rb +152 -0
  151. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  152. data/lib/active_record/fixtures.rb +275 -500
  153. data/lib/active_record/gem_version.rb +6 -4
  154. data/lib/active_record/inheritance.rb +175 -110
  155. data/lib/active_record/insert_all.rb +212 -0
  156. data/lib/active_record/integration.rb +121 -29
  157. data/lib/active_record/internal_metadata.rb +62 -0
  158. data/lib/active_record/legacy_yaml_adapter.rb +27 -5
  159. data/lib/active_record/locale/en.yml +3 -2
  160. data/lib/active_record/locking/optimistic.rb +98 -92
  161. data/lib/active_record/locking/pessimistic.rb +22 -6
  162. data/lib/active_record/log_subscriber.rb +93 -31
  163. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  164. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  165. data/lib/active_record/middleware/database_selector.rb +77 -0
  166. data/lib/active_record/migration/command_recorder.rb +185 -90
  167. data/lib/active_record/migration/compatibility.rb +295 -0
  168. data/lib/active_record/migration/join_table.rb +8 -7
  169. data/lib/active_record/migration.rb +673 -325
  170. data/lib/active_record/model_schema.rb +418 -113
  171. data/lib/active_record/nested_attributes.rb +263 -224
  172. data/lib/active_record/no_touching.rb +15 -2
  173. data/lib/active_record/null_relation.rb +24 -38
  174. data/lib/active_record/persistence.rb +572 -136
  175. data/lib/active_record/query_cache.rb +29 -23
  176. data/lib/active_record/querying.rb +50 -31
  177. data/lib/active_record/railtie.rb +170 -51
  178. data/lib/active_record/railties/console_sandbox.rb +3 -3
  179. data/lib/active_record/railties/controller_runtime.rb +34 -33
  180. data/lib/active_record/railties/databases.rake +523 -199
  181. data/lib/active_record/readonly_attributes.rb +9 -4
  182. data/lib/active_record/reflection.rb +454 -291
  183. data/lib/active_record/relation/batches/batch_enumerator.rb +85 -0
  184. data/lib/active_record/relation/batches.rb +217 -59
  185. data/lib/active_record/relation/calculations.rb +324 -249
  186. data/lib/active_record/relation/delegation.rb +76 -84
  187. data/lib/active_record/relation/finder_methods.rb +316 -242
  188. data/lib/active_record/relation/from_clause.rb +30 -0
  189. data/lib/active_record/relation/merger.rb +95 -103
  190. data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -26
  191. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
  192. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  193. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +57 -0
  194. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  195. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  196. data/lib/active_record/relation/predicate_builder.rb +136 -122
  197. data/lib/active_record/relation/query_attribute.rb +50 -0
  198. data/lib/active_record/relation/query_methods.rb +757 -413
  199. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  200. data/lib/active_record/relation/spawn_methods.rb +18 -20
  201. data/lib/active_record/relation/where_clause.rb +239 -0
  202. data/lib/active_record/relation.rb +554 -343
  203. data/lib/active_record/result.rb +91 -47
  204. data/lib/active_record/runtime_registry.rb +6 -4
  205. data/lib/active_record/sanitization.rb +134 -122
  206. data/lib/active_record/schema.rb +21 -24
  207. data/lib/active_record/schema_dumper.rb +141 -92
  208. data/lib/active_record/schema_migration.rb +24 -23
  209. data/lib/active_record/scoping/default.rb +96 -83
  210. data/lib/active_record/scoping/named.rb +78 -36
  211. data/lib/active_record/scoping.rb +45 -27
  212. data/lib/active_record/secure_token.rb +48 -0
  213. data/lib/active_record/serialization.rb +8 -6
  214. data/lib/active_record/signed_id.rb +116 -0
  215. data/lib/active_record/statement_cache.rb +89 -36
  216. data/lib/active_record/store.rb +128 -43
  217. data/lib/active_record/suppressor.rb +61 -0
  218. data/lib/active_record/table_metadata.rb +81 -0
  219. data/lib/active_record/tasks/database_tasks.rb +364 -130
  220. data/lib/active_record/tasks/mysql_database_tasks.rb +67 -113
  221. data/lib/active_record/tasks/postgresql_database_tasks.rb +86 -49
  222. data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -19
  223. data/lib/active_record/test_databases.rb +24 -0
  224. data/lib/active_record/test_fixtures.rb +287 -0
  225. data/lib/active_record/timestamp.rb +86 -43
  226. data/lib/active_record/touch_later.rb +65 -0
  227. data/lib/active_record/transactions.rb +182 -163
  228. data/lib/active_record/translation.rb +3 -1
  229. data/lib/active_record/type/adapter_specific_registry.rb +126 -0
  230. data/lib/active_record/type/date.rb +4 -45
  231. data/lib/active_record/type/date_time.rb +4 -49
  232. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  233. data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
  234. data/lib/active_record/type/internal/timezone.rb +17 -0
  235. data/lib/active_record/type/json.rb +30 -0
  236. data/lib/active_record/type/serialized.rb +27 -15
  237. data/lib/active_record/type/text.rb +2 -2
  238. data/lib/active_record/type/time.rb +21 -16
  239. data/lib/active_record/type/type_map.rb +16 -19
  240. data/lib/active_record/type/unsigned_integer.rb +9 -8
  241. data/lib/active_record/type.rb +84 -23
  242. data/lib/active_record/type_caster/connection.rb +33 -0
  243. data/lib/active_record/type_caster/map.rb +23 -0
  244. data/lib/active_record/type_caster.rb +9 -0
  245. data/lib/active_record/validations/absence.rb +25 -0
  246. data/lib/active_record/validations/associated.rb +12 -4
  247. data/lib/active_record/validations/length.rb +26 -0
  248. data/lib/active_record/validations/numericality.rb +35 -0
  249. data/lib/active_record/validations/presence.rb +14 -13
  250. data/lib/active_record/validations/uniqueness.rb +63 -56
  251. data/lib/active_record/validations.rb +39 -35
  252. data/lib/active_record/version.rb +3 -1
  253. data/lib/active_record.rb +42 -29
  254. data/lib/arel/alias_predication.rb +9 -0
  255. data/lib/arel/attributes/attribute.rb +41 -0
  256. data/lib/arel/collectors/bind.rb +29 -0
  257. data/lib/arel/collectors/composite.rb +39 -0
  258. data/lib/arel/collectors/plain_string.rb +20 -0
  259. data/lib/arel/collectors/sql_string.rb +27 -0
  260. data/lib/arel/collectors/substitute_binds.rb +35 -0
  261. data/lib/arel/crud.rb +42 -0
  262. data/lib/arel/delete_manager.rb +18 -0
  263. data/lib/arel/errors.rb +9 -0
  264. data/lib/arel/expressions.rb +29 -0
  265. data/lib/arel/factory_methods.rb +49 -0
  266. data/lib/arel/insert_manager.rb +49 -0
  267. data/lib/arel/math.rb +45 -0
  268. data/lib/arel/nodes/and.rb +32 -0
  269. data/lib/arel/nodes/ascending.rb +23 -0
  270. data/lib/arel/nodes/binary.rb +126 -0
  271. data/lib/arel/nodes/bind_param.rb +44 -0
  272. data/lib/arel/nodes/case.rb +55 -0
  273. data/lib/arel/nodes/casted.rb +62 -0
  274. data/lib/arel/nodes/comment.rb +29 -0
  275. data/lib/arel/nodes/count.rb +12 -0
  276. data/lib/arel/nodes/delete_statement.rb +45 -0
  277. data/lib/arel/nodes/descending.rb +23 -0
  278. data/lib/arel/nodes/equality.rb +15 -0
  279. data/lib/arel/nodes/extract.rb +24 -0
  280. data/lib/arel/nodes/false.rb +16 -0
  281. data/lib/arel/nodes/full_outer_join.rb +8 -0
  282. data/lib/arel/nodes/function.rb +44 -0
  283. data/lib/arel/nodes/grouping.rb +11 -0
  284. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  285. data/lib/arel/nodes/in.rb +15 -0
  286. data/lib/arel/nodes/infix_operation.rb +92 -0
  287. data/lib/arel/nodes/inner_join.rb +8 -0
  288. data/lib/arel/nodes/insert_statement.rb +37 -0
  289. data/lib/arel/nodes/join_source.rb +20 -0
  290. data/lib/arel/nodes/matches.rb +18 -0
  291. data/lib/arel/nodes/named_function.rb +23 -0
  292. data/lib/arel/nodes/node.rb +51 -0
  293. data/lib/arel/nodes/node_expression.rb +13 -0
  294. data/lib/arel/nodes/ordering.rb +27 -0
  295. data/lib/arel/nodes/outer_join.rb +8 -0
  296. data/lib/arel/nodes/over.rb +15 -0
  297. data/lib/arel/nodes/regexp.rb +16 -0
  298. data/lib/arel/nodes/right_outer_join.rb +8 -0
  299. data/lib/arel/nodes/select_core.rb +67 -0
  300. data/lib/arel/nodes/select_statement.rb +41 -0
  301. data/lib/arel/nodes/sql_literal.rb +19 -0
  302. data/lib/arel/nodes/string_join.rb +11 -0
  303. data/lib/arel/nodes/table_alias.rb +31 -0
  304. data/lib/arel/nodes/terminal.rb +16 -0
  305. data/lib/arel/nodes/true.rb +16 -0
  306. data/lib/arel/nodes/unary.rb +44 -0
  307. data/lib/arel/nodes/unary_operation.rb +20 -0
  308. data/lib/arel/nodes/unqualified_column.rb +22 -0
  309. data/lib/arel/nodes/update_statement.rb +41 -0
  310. data/lib/arel/nodes/values_list.rb +9 -0
  311. data/lib/arel/nodes/window.rb +126 -0
  312. data/lib/arel/nodes/with.rb +11 -0
  313. data/lib/arel/nodes.rb +70 -0
  314. data/lib/arel/order_predications.rb +13 -0
  315. data/lib/arel/predications.rb +250 -0
  316. data/lib/arel/select_manager.rb +270 -0
  317. data/lib/arel/table.rb +118 -0
  318. data/lib/arel/tree_manager.rb +72 -0
  319. data/lib/arel/update_manager.rb +34 -0
  320. data/lib/arel/visitors/dot.rb +308 -0
  321. data/lib/arel/visitors/mysql.rb +93 -0
  322. data/lib/arel/visitors/postgresql.rb +120 -0
  323. data/lib/arel/visitors/sqlite.rb +38 -0
  324. data/lib/arel/visitors/to_sql.rb +899 -0
  325. data/lib/arel/visitors/visitor.rb +45 -0
  326. data/lib/arel/visitors.rb +13 -0
  327. data/lib/arel/window_predications.rb +9 -0
  328. data/lib/arel.rb +54 -0
  329. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  330. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  331. data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -37
  332. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +26 -0
  333. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +13 -4
  334. data/lib/rails/generators/active_record/migration.rb +35 -1
  335. data/lib/rails/generators/active_record/model/model_generator.rb +55 -22
  336. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  337. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  338. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  339. data/lib/rails/generators/active_record.rb +7 -5
  340. metadata +172 -65
  341. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  342. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  343. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  344. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  345. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  346. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  347. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  348. data/lib/active_record/attribute.rb +0 -163
  349. data/lib/active_record/attribute_decorators.rb +0 -66
  350. data/lib/active_record/attribute_set/builder.rb +0 -106
  351. data/lib/active_record/attribute_set.rb +0 -81
  352. data/lib/active_record/connection_adapters/connection_specification.rb +0 -275
  353. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  354. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  355. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  356. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  357. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  358. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  359. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  360. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  361. data/lib/active_record/type/big_integer.rb +0 -13
  362. data/lib/active_record/type/binary.rb +0 -50
  363. data/lib/active_record/type/boolean.rb +0 -31
  364. data/lib/active_record/type/decimal.rb +0 -64
  365. data/lib/active_record/type/decorator.rb +0 -14
  366. data/lib/active_record/type/float.rb +0 -19
  367. data/lib/active_record/type/integer.rb +0 -59
  368. data/lib/active_record/type/mutable.rb +0 -16
  369. data/lib/active_record/type/numeric.rb +0 -36
  370. data/lib/active_record/type/string.rb +0 -40
  371. data/lib/active_record/type/time_value.rb +0 -38
  372. data/lib/active_record/type/value.rb +0 -110
  373. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -19
  374. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
@@ -1,35 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # See ActiveRecord::Transactions::ClassMethods for documentation.
3
5
  module Transactions
4
6
  extend ActiveSupport::Concern
5
7
  #:nodoc:
6
8
  ACTIONS = [:create, :destroy, :update]
7
- #:nodoc:
8
- CALLBACK_WARN_MESSAGE = "Currently, Active Record suppresses errors raised " \
9
- "within `after_rollback`/`after_commit` callbacks and only print them to " \
10
- "the logs. In the next version, these errors will no longer be suppressed. " \
11
- "Instead, the errors will propagate normally just like in other Active " \
12
- "Record callbacks.\n" \
13
- "\n" \
14
- "You can opt into the new behavior and remove this warning by setting:\n" \
15
- "\n" \
16
- " config.active_record.raise_in_transactional_callbacks = true\n\n"
17
9
 
18
10
  included do
19
11
  define_callbacks :commit, :rollback,
20
- terminator: ->(_, result) { result == false },
12
+ :before_commit,
21
13
  scope: [:kind, :name]
22
-
23
- mattr_accessor :raise_in_transactional_callbacks, instance_writer: false
24
- self.raise_in_transactional_callbacks = false
25
14
  end
26
15
 
27
16
  # = Active Record Transactions
28
17
  #
29
- # Transactions are protective blocks where SQL statements are only permanent
18
+ # \Transactions are protective blocks where SQL statements are only permanent
30
19
  # if they can all succeed as one atomic action. The classic example is a
31
20
  # transfer between two accounts where you can only have a deposit if the
32
- # withdrawal succeeded and vice versa. Transactions enforce the integrity of
21
+ # withdrawal succeeded and vice versa. \Transactions enforce the integrity of
33
22
  # the database and guard the data against program errors or database
34
23
  # break-downs. So basically you should use transaction blocks whenever you
35
24
  # have a number of statements that must be executed together or not at all.
@@ -49,20 +38,20 @@ module ActiveRecord
49
38
  #
50
39
  # == Different Active Record classes in a single transaction
51
40
  #
52
- # Though the transaction class method is called on some Active Record class,
41
+ # Though the #transaction class method is called on some Active Record class,
53
42
  # the objects within the transaction block need not all be instances of
54
43
  # that class. This is because transactions are per-database connection, not
55
44
  # per-model.
56
45
  #
57
46
  # In this example a +balance+ record is transactionally saved even
58
- # though +transaction+ is called on the +Account+ class:
47
+ # though #transaction is called on the +Account+ class:
59
48
  #
60
49
  # Account.transaction do
61
50
  # balance.save!
62
51
  # account.save!
63
52
  # end
64
53
  #
65
- # The +transaction+ method is also available as a model instance method.
54
+ # The #transaction method is also available as a model instance method.
66
55
  # For example, you can also do this:
67
56
  #
68
57
  # balance.transaction do
@@ -89,7 +78,8 @@ module ActiveRecord
89
78
  #
90
79
  # == +save+ and +destroy+ are automatically wrapped in a transaction
91
80
  #
92
- # Both +save+ and +destroy+ come wrapped in a transaction that ensures
81
+ # Both {#save}[rdoc-ref:Persistence#save] and
82
+ # {#destroy}[rdoc-ref:Persistence#destroy] come wrapped in a transaction that ensures
93
83
  # that whatever you do in validations or callbacks will happen under its
94
84
  # protected cover. So you can use validations to check for values that
95
85
  # the transaction depends on or you can raise exceptions in the callbacks
@@ -98,7 +88,7 @@ module ActiveRecord
98
88
  # As a consequence changes to the database are not seen outside your connection
99
89
  # until the operation is complete. For example, if you try to update the index
100
90
  # of a search engine in +after_save+ the indexer won't see the updated record.
101
- # The +after_commit+ callback is the only one that is triggered once the update
91
+ # The #after_commit callback is the only one that is triggered once the update
102
92
  # is committed. See below.
103
93
  #
104
94
  # == Exception handling and rolling back
@@ -107,11 +97,11 @@ module ActiveRecord
107
97
  # be propagated (after triggering the ROLLBACK), so you should be ready to
108
98
  # catch those in your application code.
109
99
  #
110
- # One exception is the <tt>ActiveRecord::Rollback</tt> exception, which will trigger
100
+ # One exception is the ActiveRecord::Rollback exception, which will trigger
111
101
  # a ROLLBACK when raised, but not be re-raised by the transaction block.
112
102
  #
113
- # *Warning*: one should not catch <tt>ActiveRecord::StatementInvalid</tt> exceptions
114
- # inside a transaction block. <tt>ActiveRecord::StatementInvalid</tt> exceptions indicate that an
103
+ # *Warning*: one should not catch ActiveRecord::StatementInvalid exceptions
104
+ # inside a transaction block. ActiveRecord::StatementInvalid exceptions indicate that an
115
105
  # error occurred at the database level, for example when a unique constraint
116
106
  # is violated. On some database systems, such as PostgreSQL, database errors
117
107
  # inside a transaction cause the entire transaction to become unusable
@@ -132,16 +122,16 @@ module ActiveRecord
132
122
  # # statement will cause a PostgreSQL error, even though the unique
133
123
  # # constraint is no longer violated:
134
124
  # Number.create(i: 1)
135
- # # => "PGError: ERROR: current transaction is aborted, commands
125
+ # # => "PG::Error: ERROR: current transaction is aborted, commands
136
126
  # # ignored until end of transaction block"
137
127
  # end
138
128
  #
139
129
  # One should restart the entire transaction if an
140
- # <tt>ActiveRecord::StatementInvalid</tt> occurred.
130
+ # ActiveRecord::StatementInvalid occurred.
141
131
  #
142
132
  # == Nested transactions
143
133
  #
144
- # +transaction+ calls can be nested. By default, this makes all database
134
+ # #transaction calls can be nested. By default, this makes all database
145
135
  # statements in the nested transaction block become part of the parent
146
136
  # transaction. For example, the following behavior may be surprising:
147
137
  #
@@ -153,7 +143,7 @@ module ActiveRecord
153
143
  # end
154
144
  # end
155
145
  #
156
- # creates both "Kotori" and "Nemu". Reason is the <tt>ActiveRecord::Rollback</tt>
146
+ # creates both "Kotori" and "Nemu". Reason is the ActiveRecord::Rollback
157
147
  # exception in the nested block does not issue a ROLLBACK. Since these exceptions
158
148
  # are captured in transaction blocks, the parent block does not see it and the
159
149
  # real transaction is committed.
@@ -171,34 +161,34 @@ module ActiveRecord
171
161
  # end
172
162
  # end
173
163
  #
174
- # only "Kotori" is created. This works on MySQL and PostgreSQL. SQLite3 version >= '3.6.8' also supports it.
164
+ # only "Kotori" is created.
175
165
  #
176
166
  # Most databases don't support true nested transactions. At the time of
177
167
  # writing, the only database that we're aware of that supports true nested
178
168
  # transactions, is MS-SQL. Because of this, Active Record emulates nested
179
- # transactions by using savepoints on MySQL and PostgreSQL. See
180
- # http://dev.mysql.com/doc/refman/5.6/en/savepoint.html
169
+ # transactions by using savepoints. See
170
+ # https://dev.mysql.com/doc/refman/en/savepoint.html
181
171
  # for more information about savepoints.
182
172
  #
183
- # === Callbacks
173
+ # === \Callbacks
184
174
  #
185
175
  # There are two types of callbacks associated with committing and rolling back transactions:
186
- # +after_commit+ and +after_rollback+.
176
+ # #after_commit and #after_rollback.
187
177
  #
188
- # +after_commit+ callbacks are called on every record saved or destroyed within a
189
- # transaction immediately after the transaction is committed. +after_rollback+ callbacks
178
+ # #after_commit callbacks are called on every record saved or destroyed within a
179
+ # transaction immediately after the transaction is committed. #after_rollback callbacks
190
180
  # are called on every record saved or destroyed within a transaction immediately after the
191
181
  # transaction or savepoint is rolled back.
192
182
  #
193
183
  # These callbacks are useful for interacting with other systems since you will be guaranteed
194
184
  # that the callback is only executed when the database is in a permanent state. For example,
195
- # +after_commit+ is a good spot to put in a hook to clearing a cache since clearing it from
185
+ # #after_commit is a good spot to put in a hook to clearing a cache since clearing it from
196
186
  # within a transaction could trigger the cache to be regenerated before the database is updated.
197
187
  #
198
188
  # === Caveats
199
189
  #
200
- # If you're on MySQL, then do not use DDL operations in nested transactions
201
- # blocks that are emulated with savepoints. That is, do not execute statements
190
+ # If you're on MySQL, then do not use Data Definition Language (DDL) operations in nested
191
+ # transactions blocks that are emulated with savepoints. That is, do not execute statements
202
192
  # like 'CREATE TABLE' inside such blocks. This is because MySQL automatically
203
193
  # releases all savepoints upon executing a DDL operation. When +transaction+
204
194
  # is finished and tries to release the savepoint it created earlier, a
@@ -206,18 +196,22 @@ module ActiveRecord
206
196
  # automatically released. The following example demonstrates the problem:
207
197
  #
208
198
  # Model.connection.transaction do # BEGIN
209
- # Model.connection.transaction(requires_new: true) do # CREATE SAVEPOINT active_record_1
199
+ # Model.connection.transaction(requires_new: true) do # CREATE SAVEPOINT active_record_1
210
200
  # Model.connection.create_table(...) # active_record_1 now automatically released
211
- # end # RELEASE savepoint active_record_1
201
+ # end # RELEASE SAVEPOINT active_record_1
212
202
  # # ^^^^ BOOM! database error!
213
203
  # end
214
204
  #
215
205
  # Note that "TRUNCATE" is also a MySQL DDL statement!
216
206
  module ClassMethods
217
- # See ActiveRecord::Transactions::ClassMethods for detailed documentation.
218
- def transaction(options = {}, &block)
219
- # See the ConnectionAdapters::DatabaseStatements#transaction API docs.
220
- connection.transaction(options, &block)
207
+ # See the ConnectionAdapters::DatabaseStatements#transaction API docs.
208
+ def transaction(**options, &block)
209
+ connection.transaction(**options, &block)
210
+ end
211
+
212
+ def before_commit(*args, &block) # :nodoc:
213
+ set_options_for_callbacks!(args)
214
+ set_callback(:before_commit, :before, *args, &block)
221
215
  end
222
216
 
223
217
  # This callback is called after a record has been created, updated, or destroyed.
@@ -232,109 +226,114 @@ module ActiveRecord
232
226
  # after_commit :do_foo_bar, on: [:create, :update]
233
227
  # after_commit :do_bar_baz, on: [:update, :destroy]
234
228
  #
235
- # Note that transactional fixtures do not play well with this feature. Please
236
- # use the +test_after_commit+ gem to have these hooks fired in tests.
237
229
  def after_commit(*args, &block)
238
230
  set_options_for_callbacks!(args)
239
231
  set_callback(:commit, :after, *args, &block)
240
- unless ActiveRecord::Base.raise_in_transactional_callbacks
241
- ActiveSupport::Deprecation.warn(CALLBACK_WARN_MESSAGE)
242
- end
232
+ end
233
+
234
+ # Shortcut for <tt>after_commit :hook, on: [ :create, :update ]</tt>.
235
+ def after_save_commit(*args, &block)
236
+ set_options_for_callbacks!(args, on: [ :create, :update ])
237
+ set_callback(:commit, :after, *args, &block)
238
+ end
239
+
240
+ # Shortcut for <tt>after_commit :hook, on: :create</tt>.
241
+ def after_create_commit(*args, &block)
242
+ set_options_for_callbacks!(args, on: :create)
243
+ set_callback(:commit, :after, *args, &block)
244
+ end
245
+
246
+ # Shortcut for <tt>after_commit :hook, on: :update</tt>.
247
+ def after_update_commit(*args, &block)
248
+ set_options_for_callbacks!(args, on: :update)
249
+ set_callback(:commit, :after, *args, &block)
250
+ end
251
+
252
+ # Shortcut for <tt>after_commit :hook, on: :destroy</tt>.
253
+ def after_destroy_commit(*args, &block)
254
+ set_options_for_callbacks!(args, on: :destroy)
255
+ set_callback(:commit, :after, *args, &block)
243
256
  end
244
257
 
245
258
  # This callback is called after a create, update, or destroy are rolled back.
246
259
  #
247
- # Please check the documentation of +after_commit+ for options.
260
+ # Please check the documentation of #after_commit for options.
248
261
  def after_rollback(*args, &block)
249
262
  set_options_for_callbacks!(args)
250
263
  set_callback(:rollback, :after, *args, &block)
251
- unless ActiveRecord::Base.raise_in_transactional_callbacks
252
- ActiveSupport::Deprecation.warn(CALLBACK_WARN_MESSAGE)
253
- end
254
264
  end
255
265
 
256
266
  private
267
+ def set_options_for_callbacks!(args, enforced_options = {})
268
+ options = args.extract_options!.merge!(enforced_options)
269
+ args << options
257
270
 
258
- def set_options_for_callbacks!(args)
259
- options = args.last
260
- if options.is_a?(Hash) && options[:on]
261
- fire_on = Array(options[:on])
262
- assert_valid_transaction_action(fire_on)
263
- options[:if] = Array(options[:if])
264
- options[:if] << "transaction_include_any_action?(#{fire_on})"
271
+ if options[:on]
272
+ fire_on = Array(options[:on])
273
+ assert_valid_transaction_action(fire_on)
274
+ options[:if] = [
275
+ -> { transaction_include_any_action?(fire_on) },
276
+ *options[:if]
277
+ ]
278
+ end
265
279
  end
266
- end
267
280
 
268
- def assert_valid_transaction_action(actions)
269
- if (actions - ACTIONS).any?
270
- raise ArgumentError, ":on conditions for after_commit and after_rollback callbacks have to be one of #{ACTIONS}"
281
+ def assert_valid_transaction_action(actions)
282
+ if (actions - ACTIONS).any?
283
+ raise ArgumentError, ":on conditions for after_commit and after_rollback callbacks have to be one of #{ACTIONS}"
284
+ end
271
285
  end
272
- end
273
286
  end
274
287
 
275
288
  # See ActiveRecord::Transactions::ClassMethods for detailed documentation.
276
- def transaction(options = {}, &block)
277
- self.class.transaction(options, &block)
289
+ def transaction(**options, &block)
290
+ self.class.transaction(**options, &block)
278
291
  end
279
292
 
280
293
  def destroy #:nodoc:
281
294
  with_transaction_returning_status { super }
282
295
  end
283
296
 
284
- def save(*) #:nodoc:
285
- rollback_active_record_state! do
286
- with_transaction_returning_status { super }
287
- end
297
+ def save(**) #:nodoc:
298
+ with_transaction_returning_status { super }
288
299
  end
289
300
 
290
- def save!(*) #:nodoc:
301
+ def save!(**) #:nodoc:
291
302
  with_transaction_returning_status { super }
292
303
  end
293
304
 
294
- def touch(*) #:nodoc:
305
+ def touch(*, **) #:nodoc:
295
306
  with_transaction_returning_status { super }
296
307
  end
297
308
 
298
- # Reset id and @new_record if the transaction rolls back.
299
- def rollback_active_record_state!
300
- remember_transaction_record_state
301
- yield
302
- rescue Exception
303
- restore_transaction_record_state
304
- raise
305
- ensure
306
- clear_transaction_record_state
309
+ def before_committed! # :nodoc:
310
+ _run_before_commit_callbacks
307
311
  end
308
312
 
309
- # Call the +after_commit+ callbacks.
313
+ # Call the #after_commit callbacks.
310
314
  #
311
315
  # Ensure that it is not called if the object was never persisted (failed create),
312
316
  # but call it after the commit of a destroyed object.
313
- def committed!(should_run_callbacks = true) #:nodoc:
314
- _run_commit_callbacks if should_run_callbacks && destroyed? || persisted?
315
- ensure
317
+ def committed!(should_run_callbacks: true) #:nodoc:
316
318
  force_clear_transaction_record_state
319
+ if should_run_callbacks
320
+ @_committed_already_called = true
321
+ _run_commit_callbacks
322
+ end
323
+ ensure
324
+ @_committed_already_called = @_trigger_update_callback = @_trigger_destroy_callback = false
317
325
  end
318
326
 
319
- # Call the +after_rollback+ callbacks. The +force_restore_state+ argument indicates if the record
327
+ # Call the #after_rollback callbacks. The +force_restore_state+ argument indicates if the record
320
328
  # state should be rolled back to the beginning or just to the last savepoint.
321
- def rolledback!(force_restore_state = false, should_run_callbacks = true) #:nodoc:
322
- _run_rollback_callbacks if should_run_callbacks
329
+ def rolledback!(force_restore_state: false, should_run_callbacks: true) #:nodoc:
330
+ if should_run_callbacks
331
+ _run_rollback_callbacks
332
+ end
323
333
  ensure
324
334
  restore_transaction_record_state(force_restore_state)
325
335
  clear_transaction_record_state
326
- end
327
-
328
- # Add the record to the current transaction so that the +after_rollback+ and +after_commit+ callbacks
329
- # can be called.
330
- def add_to_transaction
331
- if has_transactional_callbacks?
332
- self.class.connection.add_transaction_record(self)
333
- else
334
- sync_with_transaction_state
335
- set_transaction_state(self.class.connection.transaction_state)
336
- end
337
- remember_transaction_record_state
336
+ @_trigger_update_callback = @_trigger_destroy_callback = false if force_restore_state
338
337
  end
339
338
 
340
339
  # Executes +method+ within a transaction and captures its return value as a
@@ -345,83 +344,103 @@ module ActiveRecord
345
344
  # instance.
346
345
  def with_transaction_returning_status
347
346
  status = nil
348
- self.class.transaction do
349
- add_to_transaction
350
- begin
351
- status = yield
352
- rescue ActiveRecord::Rollback
353
- clear_transaction_record_state
354
- status = nil
355
- end
347
+ connection = self.class.connection
348
+ ensure_finalize = !connection.transaction_open?
356
349
 
350
+ connection.transaction do
351
+ add_to_transaction(ensure_finalize || has_transactional_callbacks?)
352
+ remember_transaction_record_state
353
+
354
+ status = yield
357
355
  raise ActiveRecord::Rollback unless status
358
356
  end
359
357
  status
360
- ensure
361
- if @transaction_state && @transaction_state.committed?
362
- clear_transaction_record_state
363
- end
364
358
  end
365
359
 
366
- protected
367
-
368
- # Save the new record state and id of a record so it can be restored later if a transaction fails.
369
- def remember_transaction_record_state #:nodoc:
370
- @_start_transaction_state[:id] = id
371
- @_start_transaction_state.reverse_merge!(
372
- new_record: @new_record,
373
- destroyed: @destroyed,
374
- frozen?: frozen?,
375
- )
376
- @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) + 1
360
+ def trigger_transactional_callbacks? # :nodoc:
361
+ (@_new_record_before_last_commit || _trigger_update_callback) && persisted? ||
362
+ _trigger_destroy_callback && destroyed?
377
363
  end
378
364
 
379
- # Clear the new record state and id of a record.
380
- def clear_transaction_record_state #:nodoc:
381
- @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1
382
- force_clear_transaction_record_state if @_start_transaction_state[:level] < 1
383
- end
365
+ private
366
+ attr_reader :_committed_already_called, :_trigger_update_callback, :_trigger_destroy_callback
384
367
 
385
- # Force to clear the transaction record state.
386
- def force_clear_transaction_record_state #:nodoc:
387
- @_start_transaction_state.clear
388
- end
368
+ # Save the new record state and id of a record so it can be restored later if a transaction fails.
369
+ def remember_transaction_record_state
370
+ @_start_transaction_state ||= {
371
+ id: id,
372
+ new_record: @new_record,
373
+ previously_new_record: @previously_new_record,
374
+ destroyed: @destroyed,
375
+ attributes: @attributes,
376
+ frozen?: frozen?,
377
+ level: 0
378
+ }
379
+ @_start_transaction_state[:level] += 1
389
380
 
390
- # Restore the new record state and id of a record that was previously saved by a call to save_record_state.
391
- def restore_transaction_record_state(force = false) #:nodoc:
392
- unless @_start_transaction_state.empty?
393
- transaction_level = (@_start_transaction_state[:level] || 0) - 1
394
- if transaction_level < 1 || force
395
- restore_state = @_start_transaction_state
396
- thaw
397
- @new_record = restore_state[:new_record]
398
- @destroyed = restore_state[:destroyed]
399
- pk = self.class.primary_key
400
- if pk && read_attribute(pk) != restore_state[:id]
401
- write_attribute(pk, restore_state[:id])
402
- end
403
- freeze if restore_state[:frozen?]
381
+ if _committed_already_called
382
+ @_new_record_before_last_commit = false
383
+ else
384
+ @_new_record_before_last_commit = @_start_transaction_state[:new_record]
404
385
  end
405
386
  end
406
- end
407
387
 
408
- # Determine if a record was created or destroyed in a transaction. State should be one of :new_record or :destroyed.
409
- def transaction_record_state(state) #:nodoc:
410
- @_start_transaction_state[state]
411
- end
388
+ # Clear the new record state and id of a record.
389
+ def clear_transaction_record_state
390
+ return unless @_start_transaction_state
391
+ @_start_transaction_state[:level] -= 1
392
+ force_clear_transaction_record_state if @_start_transaction_state[:level] < 1
393
+ end
394
+
395
+ # Force to clear the transaction record state.
396
+ def force_clear_transaction_record_state
397
+ @_start_transaction_state = nil
398
+ end
412
399
 
413
- # Determine if a transaction included an action for :create, :update, or :destroy. Used in filtering callbacks.
414
- def transaction_include_any_action?(actions) #:nodoc:
415
- actions.any? do |action|
416
- case action
417
- when :create
418
- transaction_record_state(:new_record)
419
- when :destroy
420
- destroyed?
421
- when :update
422
- !(transaction_record_state(:new_record) || destroyed?)
400
+ # Restore the new record state and id of a record that was previously saved by a call to save_record_state.
401
+ def restore_transaction_record_state(force_restore_state = false)
402
+ if restore_state = @_start_transaction_state
403
+ if force_restore_state || restore_state[:level] <= 1
404
+ @new_record = restore_state[:new_record]
405
+ @previously_new_record = restore_state[:previously_new_record]
406
+ @destroyed = restore_state[:destroyed]
407
+ @attributes = restore_state[:attributes].map do |attr|
408
+ value = @attributes.fetch_value(attr.name)
409
+ attr = attr.with_value_from_user(value) if attr.value != value
410
+ attr
411
+ end
412
+ @mutations_from_database = nil
413
+ @mutations_before_last_save = nil
414
+ if @attributes.fetch_value(@primary_key) != restore_state[:id]
415
+ @attributes.write_from_user(@primary_key, restore_state[:id])
416
+ end
417
+ freeze if restore_state[:frozen?]
418
+ end
423
419
  end
424
420
  end
425
- end
421
+
422
+ # Determine if a transaction included an action for :create, :update, or :destroy. Used in filtering callbacks.
423
+ def transaction_include_any_action?(actions)
424
+ actions.any? do |action|
425
+ case action
426
+ when :create
427
+ persisted? && @_new_record_before_last_commit
428
+ when :update
429
+ !(@_new_record_before_last_commit || destroyed?) && _trigger_update_callback
430
+ when :destroy
431
+ _trigger_destroy_callback
432
+ end
433
+ end
434
+ end
435
+
436
+ # Add the record to the current transaction so that the #after_rollback and #after_commit
437
+ # callbacks can be called.
438
+ def add_to_transaction(ensure_finalize = true)
439
+ self.class.connection.add_transaction_record(self, ensure_finalize)
440
+ end
441
+
442
+ def has_transactional_callbacks?
443
+ !_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_before_commit_callbacks.empty?
444
+ end
426
445
  end
427
446
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Translation
3
5
  include ActiveModel::Translation
@@ -8,7 +10,7 @@ module ActiveRecord
8
10
  classes = [klass]
9
11
  return classes if klass == ActiveRecord::Base
10
12
 
11
- while klass != klass.base_class
13
+ while !klass.base_class?
12
14
  classes << klass = klass.superclass
13
15
  end
14
16
  classes
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_model/type/registry"
4
+
5
+ module ActiveRecord
6
+ # :stopdoc:
7
+ module Type
8
+ class AdapterSpecificRegistry < ActiveModel::Type::Registry
9
+ def add_modifier(options, klass, **args)
10
+ registrations << DecorationRegistration.new(options, klass, **args)
11
+ end
12
+
13
+ private
14
+ def registration_klass
15
+ Registration
16
+ end
17
+
18
+ def find_registration(symbol, *args, **kwargs)
19
+ registrations
20
+ .select { |registration| registration.matches?(symbol, *args, **kwargs) }
21
+ .max
22
+ end
23
+ end
24
+
25
+ class Registration
26
+ def initialize(name, block, adapter: nil, override: nil)
27
+ @name = name
28
+ @block = block
29
+ @adapter = adapter
30
+ @override = override
31
+ end
32
+
33
+ def call(_registry, *args, adapter: nil, **kwargs)
34
+ if kwargs.any? # https://bugs.ruby-lang.org/issues/10856
35
+ block.call(*args, **kwargs)
36
+ else
37
+ block.call(*args)
38
+ end
39
+ end
40
+
41
+ def matches?(type_name, *args, **kwargs)
42
+ type_name == name && matches_adapter?(**kwargs)
43
+ end
44
+
45
+ def <=>(other)
46
+ if conflicts_with?(other)
47
+ raise TypeConflictError.new("Type #{name} was registered for all
48
+ adapters, but shadows a native type with
49
+ the same name for #{other.adapter}".squish)
50
+ end
51
+ priority <=> other.priority
52
+ end
53
+
54
+ protected
55
+ attr_reader :name, :block, :adapter, :override
56
+
57
+ def priority
58
+ result = 0
59
+ if adapter
60
+ result |= 1
61
+ end
62
+ if override
63
+ result |= 2
64
+ end
65
+ result
66
+ end
67
+
68
+ def priority_except_adapter
69
+ priority & 0b111111100
70
+ end
71
+
72
+ private
73
+ def matches_adapter?(adapter: nil, **)
74
+ (self.adapter.nil? || adapter == self.adapter)
75
+ end
76
+
77
+ def conflicts_with?(other)
78
+ same_priority_except_adapter?(other) &&
79
+ has_adapter_conflict?(other)
80
+ end
81
+
82
+ def same_priority_except_adapter?(other)
83
+ priority_except_adapter == other.priority_except_adapter
84
+ end
85
+
86
+ def has_adapter_conflict?(other)
87
+ (override.nil? && other.adapter) ||
88
+ (adapter && other.override.nil?)
89
+ end
90
+ end
91
+
92
+ class DecorationRegistration < Registration
93
+ def initialize(options, klass, adapter: nil)
94
+ @options = options
95
+ @klass = klass
96
+ @adapter = adapter
97
+ end
98
+
99
+ def call(registry, *args, **kwargs)
100
+ subtype = registry.lookup(*args, **kwargs.except(*options.keys))
101
+ klass.new(subtype)
102
+ end
103
+
104
+ def matches?(*args, **kwargs)
105
+ matches_adapter?(**kwargs) && matches_options?(**kwargs)
106
+ end
107
+
108
+ def priority
109
+ super | 4
110
+ end
111
+
112
+ private
113
+ attr_reader :options, :klass
114
+
115
+ def matches_options?(**kwargs)
116
+ options.all? do |key, value|
117
+ kwargs[key] == value
118
+ end
119
+ end
120
+ end
121
+ end
122
+
123
+ class TypeConflictError < StandardError
124
+ end
125
+ # :startdoc:
126
+ end