activerecord 5.2.4.4 → 6.0.3.4

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 (292) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +777 -552
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +5 -3
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record.rb +10 -2
  7. data/lib/active_record/advisory_lock_base.rb +18 -0
  8. data/lib/active_record/aggregations.rb +4 -3
  9. data/lib/active_record/association_relation.rb +10 -8
  10. data/lib/active_record/associations.rb +21 -16
  11. data/lib/active_record/associations/alias_tracker.rb +0 -1
  12. data/lib/active_record/associations/association.rb +56 -19
  13. data/lib/active_record/associations/association_scope.rb +4 -6
  14. data/lib/active_record/associations/belongs_to_association.rb +36 -42
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
  16. data/lib/active_record/associations/builder/association.rb +14 -18
  17. data/lib/active_record/associations/builder/belongs_to.rb +19 -52
  18. data/lib/active_record/associations/builder/collection_association.rb +3 -13
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -40
  20. data/lib/active_record/associations/builder/has_many.rb +2 -0
  21. data/lib/active_record/associations/builder/has_one.rb +35 -1
  22. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  23. data/lib/active_record/associations/collection_association.rb +12 -23
  24. data/lib/active_record/associations/collection_proxy.rb +13 -17
  25. data/lib/active_record/associations/foreign_association.rb +7 -0
  26. data/lib/active_record/associations/has_many_association.rb +2 -11
  27. data/lib/active_record/associations/has_many_through_association.rb +14 -14
  28. data/lib/active_record/associations/has_one_association.rb +28 -30
  29. data/lib/active_record/associations/has_one_through_association.rb +5 -5
  30. data/lib/active_record/associations/join_dependency.rb +37 -28
  31. data/lib/active_record/associations/join_dependency/join_association.rb +9 -10
  32. data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
  33. data/lib/active_record/associations/preloader.rb +39 -32
  34. data/lib/active_record/associations/preloader/association.rb +38 -36
  35. data/lib/active_record/associations/preloader/through_association.rb +48 -39
  36. data/lib/active_record/associations/singular_association.rb +2 -16
  37. data/lib/active_record/attribute_assignment.rb +7 -11
  38. data/lib/active_record/attribute_decorators.rb +0 -2
  39. data/lib/active_record/attribute_methods.rb +28 -100
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +4 -2
  41. data/lib/active_record/attribute_methods/dirty.rb +111 -40
  42. data/lib/active_record/attribute_methods/primary_key.rb +15 -24
  43. data/lib/active_record/attribute_methods/query.rb +2 -3
  44. data/lib/active_record/attribute_methods/read.rb +15 -54
  45. data/lib/active_record/attribute_methods/serialization.rb +1 -2
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -3
  47. data/lib/active_record/attribute_methods/write.rb +17 -25
  48. data/lib/active_record/attributes.rb +13 -1
  49. data/lib/active_record/autosave_association.rb +3 -5
  50. data/lib/active_record/base.rb +2 -3
  51. data/lib/active_record/callbacks.rb +6 -21
  52. data/lib/active_record/coders/yaml_column.rb +0 -1
  53. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +103 -18
  54. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -4
  55. data/lib/active_record/connection_adapters/abstract/database_statements.rb +102 -124
  56. data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -9
  57. data/lib/active_record/connection_adapters/abstract/quoting.rb +68 -17
  58. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +20 -14
  59. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +100 -72
  60. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -3
  61. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +175 -79
  62. data/lib/active_record/connection_adapters/abstract/transaction.rb +96 -57
  63. data/lib/active_record/connection_adapters/abstract_adapter.rb +191 -43
  64. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +142 -215
  65. data/lib/active_record/connection_adapters/column.rb +17 -13
  66. data/lib/active_record/connection_adapters/connection_specification.rb +54 -45
  67. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +6 -10
  68. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  69. data/lib/active_record/connection_adapters/mysql/database_statements.rb +70 -14
  70. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +0 -1
  71. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
  72. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +4 -6
  73. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +40 -32
  74. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +14 -6
  75. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +132 -16
  76. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +6 -10
  77. data/lib/active_record/connection_adapters/mysql2_adapter.rb +26 -10
  78. data/lib/active_record/connection_adapters/postgresql/column.rb +17 -31
  79. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +26 -1
  80. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  81. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  82. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  83. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
  84. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
  91. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +5 -3
  92. data/lib/active_record/connection_adapters/postgresql/quoting.rb +44 -7
  93. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
  94. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +14 -3
  95. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
  96. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  97. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +63 -75
  98. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +24 -27
  99. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  100. data/lib/active_record/connection_adapters/postgresql_adapter.rb +168 -75
  101. data/lib/active_record/connection_adapters/schema_cache.rb +37 -14
  102. data/lib/active_record/connection_adapters/sql_type_metadata.rb +11 -8
  103. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -0
  104. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
  105. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -12
  106. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +135 -146
  107. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  108. data/lib/active_record/connection_handling.rb +139 -26
  109. data/lib/active_record/core.rb +103 -61
  110. data/lib/active_record/counter_cache.rb +8 -30
  111. data/lib/active_record/database_configurations.rb +233 -0
  112. data/lib/active_record/database_configurations/database_config.rb +37 -0
  113. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  114. data/lib/active_record/database_configurations/url_config.rb +78 -0
  115. data/lib/active_record/dynamic_matchers.rb +3 -4
  116. data/lib/active_record/enum.rb +37 -7
  117. data/lib/active_record/errors.rb +15 -7
  118. data/lib/active_record/explain.rb +1 -2
  119. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  120. data/lib/active_record/fixture_set/render_context.rb +17 -0
  121. data/lib/active_record/fixture_set/table_row.rb +152 -0
  122. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  123. data/lib/active_record/fixtures.rb +144 -474
  124. data/lib/active_record/gem_version.rb +3 -3
  125. data/lib/active_record/inheritance.rb +13 -6
  126. data/lib/active_record/insert_all.rb +179 -0
  127. data/lib/active_record/integration.rb +68 -16
  128. data/lib/active_record/internal_metadata.rb +11 -3
  129. data/lib/active_record/locking/optimistic.rb +5 -7
  130. data/lib/active_record/locking/pessimistic.rb +3 -3
  131. data/lib/active_record/log_subscriber.rb +8 -27
  132. data/lib/active_record/middleware/database_selector.rb +74 -0
  133. data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
  134. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  135. data/lib/active_record/migration.rb +104 -85
  136. data/lib/active_record/migration/command_recorder.rb +54 -22
  137. data/lib/active_record/migration/compatibility.rb +79 -52
  138. data/lib/active_record/migration/join_table.rb +0 -1
  139. data/lib/active_record/model_schema.rb +33 -11
  140. data/lib/active_record/nested_attributes.rb +2 -4
  141. data/lib/active_record/no_touching.rb +9 -2
  142. data/lib/active_record/null_relation.rb +0 -1
  143. data/lib/active_record/persistence.rb +232 -29
  144. data/lib/active_record/query_cache.rb +11 -4
  145. data/lib/active_record/querying.rb +33 -21
  146. data/lib/active_record/railtie.rb +80 -43
  147. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  148. data/lib/active_record/railties/controller_runtime.rb +30 -35
  149. data/lib/active_record/railties/databases.rake +199 -46
  150. data/lib/active_record/reflection.rb +40 -38
  151. data/lib/active_record/relation.rb +322 -80
  152. data/lib/active_record/relation/batches.rb +13 -11
  153. data/lib/active_record/relation/calculations.rb +54 -48
  154. data/lib/active_record/relation/delegation.rb +33 -49
  155. data/lib/active_record/relation/finder_methods.rb +23 -28
  156. data/lib/active_record/relation/from_clause.rb +4 -0
  157. data/lib/active_record/relation/merger.rb +11 -21
  158. data/lib/active_record/relation/predicate_builder.rb +5 -11
  159. data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
  160. data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
  161. data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
  162. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  163. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
  164. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  165. data/lib/active_record/relation/query_attribute.rb +13 -8
  166. data/lib/active_record/relation/query_methods.rb +221 -70
  167. data/lib/active_record/relation/spawn_methods.rb +1 -2
  168. data/lib/active_record/relation/where_clause.rb +14 -11
  169. data/lib/active_record/relation/where_clause_factory.rb +1 -2
  170. data/lib/active_record/result.rb +30 -12
  171. data/lib/active_record/sanitization.rb +32 -40
  172. data/lib/active_record/schema.rb +2 -11
  173. data/lib/active_record/schema_dumper.rb +22 -7
  174. data/lib/active_record/schema_migration.rb +6 -2
  175. data/lib/active_record/scoping.rb +8 -9
  176. data/lib/active_record/scoping/default.rb +4 -6
  177. data/lib/active_record/scoping/named.rb +21 -17
  178. data/lib/active_record/statement_cache.rb +30 -3
  179. data/lib/active_record/store.rb +87 -8
  180. data/lib/active_record/suppressor.rb +2 -2
  181. data/lib/active_record/table_metadata.rb +23 -15
  182. data/lib/active_record/tasks/database_tasks.rb +194 -25
  183. data/lib/active_record/tasks/mysql_database_tasks.rb +5 -6
  184. data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -8
  185. data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -9
  186. data/lib/active_record/test_databases.rb +23 -0
  187. data/lib/active_record/test_fixtures.rb +225 -0
  188. data/lib/active_record/timestamp.rb +39 -26
  189. data/lib/active_record/touch_later.rb +5 -4
  190. data/lib/active_record/transactions.rb +64 -73
  191. data/lib/active_record/translation.rb +1 -1
  192. data/lib/active_record/type.rb +3 -5
  193. data/lib/active_record/type/adapter_specific_registry.rb +3 -13
  194. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  195. data/lib/active_record/type/serialized.rb +0 -1
  196. data/lib/active_record/type/type_map.rb +0 -1
  197. data/lib/active_record/type/unsigned_integer.rb +0 -1
  198. data/lib/active_record/type_caster/connection.rb +15 -14
  199. data/lib/active_record/type_caster/map.rb +1 -4
  200. data/lib/active_record/validations.rb +3 -3
  201. data/lib/active_record/validations/associated.rb +1 -2
  202. data/lib/active_record/validations/uniqueness.rb +15 -27
  203. data/lib/arel.rb +62 -0
  204. data/lib/arel/alias_predication.rb +9 -0
  205. data/lib/arel/attributes.rb +22 -0
  206. data/lib/arel/attributes/attribute.rb +37 -0
  207. data/lib/arel/collectors/bind.rb +24 -0
  208. data/lib/arel/collectors/composite.rb +31 -0
  209. data/lib/arel/collectors/plain_string.rb +20 -0
  210. data/lib/arel/collectors/sql_string.rb +20 -0
  211. data/lib/arel/collectors/substitute_binds.rb +28 -0
  212. data/lib/arel/crud.rb +42 -0
  213. data/lib/arel/delete_manager.rb +18 -0
  214. data/lib/arel/errors.rb +9 -0
  215. data/lib/arel/expressions.rb +29 -0
  216. data/lib/arel/factory_methods.rb +49 -0
  217. data/lib/arel/insert_manager.rb +49 -0
  218. data/lib/arel/math.rb +45 -0
  219. data/lib/arel/nodes.rb +68 -0
  220. data/lib/arel/nodes/and.rb +32 -0
  221. data/lib/arel/nodes/ascending.rb +23 -0
  222. data/lib/arel/nodes/binary.rb +52 -0
  223. data/lib/arel/nodes/bind_param.rb +36 -0
  224. data/lib/arel/nodes/case.rb +55 -0
  225. data/lib/arel/nodes/casted.rb +50 -0
  226. data/lib/arel/nodes/comment.rb +29 -0
  227. data/lib/arel/nodes/count.rb +12 -0
  228. data/lib/arel/nodes/delete_statement.rb +45 -0
  229. data/lib/arel/nodes/descending.rb +23 -0
  230. data/lib/arel/nodes/equality.rb +18 -0
  231. data/lib/arel/nodes/extract.rb +24 -0
  232. data/lib/arel/nodes/false.rb +16 -0
  233. data/lib/arel/nodes/full_outer_join.rb +8 -0
  234. data/lib/arel/nodes/function.rb +44 -0
  235. data/lib/arel/nodes/grouping.rb +8 -0
  236. data/lib/arel/nodes/in.rb +8 -0
  237. data/lib/arel/nodes/infix_operation.rb +80 -0
  238. data/lib/arel/nodes/inner_join.rb +8 -0
  239. data/lib/arel/nodes/insert_statement.rb +37 -0
  240. data/lib/arel/nodes/join_source.rb +20 -0
  241. data/lib/arel/nodes/matches.rb +18 -0
  242. data/lib/arel/nodes/named_function.rb +23 -0
  243. data/lib/arel/nodes/node.rb +50 -0
  244. data/lib/arel/nodes/node_expression.rb +13 -0
  245. data/lib/arel/nodes/outer_join.rb +8 -0
  246. data/lib/arel/nodes/over.rb +15 -0
  247. data/lib/arel/nodes/regexp.rb +16 -0
  248. data/lib/arel/nodes/right_outer_join.rb +8 -0
  249. data/lib/arel/nodes/select_core.rb +67 -0
  250. data/lib/arel/nodes/select_statement.rb +41 -0
  251. data/lib/arel/nodes/sql_literal.rb +16 -0
  252. data/lib/arel/nodes/string_join.rb +11 -0
  253. data/lib/arel/nodes/table_alias.rb +27 -0
  254. data/lib/arel/nodes/terminal.rb +16 -0
  255. data/lib/arel/nodes/true.rb +16 -0
  256. data/lib/arel/nodes/unary.rb +45 -0
  257. data/lib/arel/nodes/unary_operation.rb +20 -0
  258. data/lib/arel/nodes/unqualified_column.rb +22 -0
  259. data/lib/arel/nodes/update_statement.rb +41 -0
  260. data/lib/arel/nodes/values_list.rb +9 -0
  261. data/lib/arel/nodes/window.rb +126 -0
  262. data/lib/arel/nodes/with.rb +11 -0
  263. data/lib/arel/order_predications.rb +13 -0
  264. data/lib/arel/predications.rb +256 -0
  265. data/lib/arel/select_manager.rb +271 -0
  266. data/lib/arel/table.rb +110 -0
  267. data/lib/arel/tree_manager.rb +72 -0
  268. data/lib/arel/update_manager.rb +34 -0
  269. data/lib/arel/visitors.rb +20 -0
  270. data/lib/arel/visitors/depth_first.rb +203 -0
  271. data/lib/arel/visitors/dot.rb +296 -0
  272. data/lib/arel/visitors/ibm_db.rb +34 -0
  273. data/lib/arel/visitors/informix.rb +62 -0
  274. data/lib/arel/visitors/mssql.rb +156 -0
  275. data/lib/arel/visitors/mysql.rb +83 -0
  276. data/lib/arel/visitors/oracle.rb +158 -0
  277. data/lib/arel/visitors/oracle12.rb +65 -0
  278. data/lib/arel/visitors/postgresql.rb +109 -0
  279. data/lib/arel/visitors/sqlite.rb +38 -0
  280. data/lib/arel/visitors/to_sql.rb +888 -0
  281. data/lib/arel/visitors/visitor.rb +45 -0
  282. data/lib/arel/visitors/where_sql.rb +22 -0
  283. data/lib/arel/window_predications.rb +9 -0
  284. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  285. data/lib/rails/generators/active_record/migration.rb +14 -2
  286. data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
  287. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +1 -1
  288. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -2
  289. data/lib/rails/generators/active_record/model/model_generator.rb +1 -1
  290. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  291. metadata +115 -29
  292. data/lib/active_record/collection_cache_key.rb +0 -53
@@ -2,14 +2,14 @@
2
2
 
3
3
  module ActiveRecord
4
4
  # = Active Record Touch Later
5
- module TouchLater
5
+ module TouchLater # :nodoc:
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  included do
9
9
  before_commit_without_transaction_enrollment :touch_deferred_attributes
10
10
  end
11
11
 
12
- def touch_later(*names) # :nodoc:
12
+ def touch_later(*names, **) # :nodoc:
13
13
  unless persisted?
14
14
  raise ActiveRecordError, <<-MSG.squish
15
15
  cannot touch on a new or destroyed record object. Consider using
@@ -22,7 +22,8 @@ module ActiveRecord
22
22
  @_touch_time = current_time_from_proper_timezone
23
23
 
24
24
  surreptitiously_touch @_defer_touch_attrs
25
- self.class.connection.add_transaction_record self
25
+ add_to_transaction
26
+ @_new_record_before_last_commit ||= false
26
27
 
27
28
  # touch the parents as we are not calling the after_save callbacks
28
29
  self.class.reflect_on_all_associations(:belongs_to).each do |r|
@@ -40,7 +41,6 @@ module ActiveRecord
40
41
  end
41
42
 
42
43
  private
43
-
44
44
  def surreptitiously_touch(attrs)
45
45
  attrs.each { |attr| write_attribute attr, @_touch_time }
46
46
  clear_attribute_changes attrs
@@ -48,6 +48,7 @@ module ActiveRecord
48
48
 
49
49
  def touch_deferred_attributes
50
50
  if has_defer_touch_attrs? && persisted?
51
+ @_skip_dirty_tracking = true
51
52
  touch(*@_defer_touch_attrs, time: @_touch_time)
52
53
  @_defer_touch_attrs, @_touch_time = nil, nil
53
54
  end
@@ -208,8 +208,8 @@ module ActiveRecord
208
208
  # Note that "TRUNCATE" is also a MySQL DDL statement!
209
209
  module ClassMethods
210
210
  # See the ConnectionAdapters::DatabaseStatements#transaction API docs.
211
- def transaction(options = {}, &block)
212
- connection.transaction(options, &block)
211
+ def transaction(**options, &block)
212
+ connection.transaction(**options, &block)
213
213
  end
214
214
 
215
215
  def before_commit(*args, &block) # :nodoc:
@@ -234,6 +234,12 @@ module ActiveRecord
234
234
  set_callback(:commit, :after, *args, &block)
235
235
  end
236
236
 
237
+ # Shortcut for <tt>after_commit :hook, on: [ :create, :update ]</tt>.
238
+ def after_save_commit(*args, &block)
239
+ set_options_for_callbacks!(args, on: [ :create, :update ])
240
+ set_callback(:commit, :after, *args, &block)
241
+ end
242
+
237
243
  # Shortcut for <tt>after_commit :hook, on: :create</tt>.
238
244
  def after_create_commit(*args, &block)
239
245
  set_options_for_callbacks!(args, on: :create)
@@ -276,7 +282,6 @@ module ActiveRecord
276
282
  end
277
283
 
278
284
  private
279
-
280
285
  def set_options_for_callbacks!(args, enforced_options = {})
281
286
  options = args.extract_options!.merge!(enforced_options)
282
287
  args << options
@@ -298,36 +303,23 @@ module ActiveRecord
298
303
 
299
304
  # See ActiveRecord::Transactions::ClassMethods for detailed documentation.
300
305
  def transaction(options = {}, &block)
301
- self.class.transaction(options, &block)
306
+ self.class.transaction(**options, &block)
302
307
  end
303
308
 
304
309
  def destroy #:nodoc:
305
310
  with_transaction_returning_status { super }
306
311
  end
307
312
 
308
- def save(*) #:nodoc:
309
- rollback_active_record_state! do
310
- with_transaction_returning_status { super }
311
- end
312
- end
313
-
314
- def save!(*) #:nodoc:
313
+ def save(*, **) #:nodoc:
315
314
  with_transaction_returning_status { super }
316
315
  end
317
316
 
318
- def touch(*) #:nodoc:
317
+ def save!(*, **) #:nodoc:
319
318
  with_transaction_returning_status { super }
320
319
  end
321
320
 
322
- # Reset id and @new_record if the transaction rolls back.
323
- def rollback_active_record_state!
324
- remember_transaction_record_state
325
- yield
326
- rescue Exception
327
- restore_transaction_record_state
328
- raise
329
- ensure
330
- clear_transaction_record_state
321
+ def touch(*, **) #:nodoc:
322
+ with_transaction_returning_status { super }
331
323
  end
332
324
 
333
325
  def before_committed! # :nodoc:
@@ -341,13 +333,13 @@ module ActiveRecord
341
333
  # but call it after the commit of a destroyed object.
342
334
  def committed!(should_run_callbacks: true) #:nodoc:
343
335
  force_clear_transaction_record_state
344
- if should_run_callbacks && (destroyed? || persisted?)
336
+ if should_run_callbacks
345
337
  @_committed_already_called = true
346
338
  _run_commit_without_transaction_enrollment_callbacks
347
339
  _run_commit_callbacks
348
340
  end
349
341
  ensure
350
- @_committed_already_called = false
342
+ @_committed_already_called = @_trigger_update_callback = @_trigger_destroy_callback = false
351
343
  end
352
344
 
353
345
  # Call the #after_rollback callbacks. The +force_restore_state+ argument indicates if the record
@@ -360,18 +352,7 @@ module ActiveRecord
360
352
  ensure
361
353
  restore_transaction_record_state(force_restore_state)
362
354
  clear_transaction_record_state
363
- end
364
-
365
- # Add the record to the current transaction so that the #after_rollback and #after_commit callbacks
366
- # can be called.
367
- def add_to_transaction
368
- if has_transactional_callbacks?
369
- self.class.connection.add_transaction_record(self)
370
- else
371
- sync_with_transaction_state
372
- set_transaction_state(self.class.connection.transaction_state)
373
- end
374
- remember_transaction_record_state
355
+ @_trigger_update_callback = @_trigger_destroy_callback = false if force_restore_state
375
356
  end
376
357
 
377
358
  # Executes +method+ within a transaction and captures its return value as a
@@ -383,35 +364,40 @@ module ActiveRecord
383
364
  def with_transaction_returning_status
384
365
  status = nil
385
366
  self.class.transaction do
386
- add_to_transaction
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
374
+
387
375
  status = yield
388
376
  raise ActiveRecord::Rollback unless status
389
377
  end
390
378
  status
391
- ensure
392
- if @transaction_state && @transaction_state.committed?
393
- clear_transaction_record_state
394
- end
395
379
  end
396
380
 
397
- protected
398
- attr_reader :_committed_already_called, :_trigger_update_callback, :_trigger_destroy_callback
381
+ def trigger_transactional_callbacks? # :nodoc:
382
+ (@_new_record_before_last_commit || _trigger_update_callback) && persisted? ||
383
+ _trigger_destroy_callback && destroyed?
384
+ end
399
385
 
400
386
  private
387
+ attr_reader :_committed_already_called, :_trigger_update_callback, :_trigger_destroy_callback
401
388
 
402
389
  # Save the new record state and id of a record so it can be restored later if a transaction fails.
403
390
  def remember_transaction_record_state
404
- @_start_transaction_state.reverse_merge!(
391
+ @_start_transaction_state ||= {
405
392
  id: id,
406
393
  new_record: @new_record,
407
394
  destroyed: @destroyed,
395
+ attributes: @attributes,
408
396
  frozen?: frozen?,
409
- )
410
- @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) + 1
411
- remember_new_record_before_last_commit
412
- end
397
+ level: 0
398
+ }
399
+ @_start_transaction_state[:level] += 1
413
400
 
414
- def remember_new_record_before_last_commit
415
401
  if _committed_already_called
416
402
  @_new_record_before_last_commit = false
417
403
  else
@@ -421,27 +407,32 @@ module ActiveRecord
421
407
 
422
408
  # Clear the new record state and id of a record.
423
409
  def clear_transaction_record_state
424
- @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1
410
+ return unless @_start_transaction_state
411
+ @_start_transaction_state[:level] -= 1
425
412
  force_clear_transaction_record_state if @_start_transaction_state[:level] < 1
426
413
  end
427
414
 
428
415
  # Force to clear the transaction record state.
429
416
  def force_clear_transaction_record_state
430
- @_start_transaction_state.clear
417
+ @_start_transaction_state = nil
418
+ @transaction_state = nil
431
419
  end
432
420
 
433
421
  # Restore the new record state and id of a record that was previously saved by a call to save_record_state.
434
- def restore_transaction_record_state(force = false)
435
- unless @_start_transaction_state.empty?
436
- transaction_level = (@_start_transaction_state[:level] || 0) - 1
437
- if transaction_level < 1 || force
438
- restore_state = @_start_transaction_state
439
- thaw
422
+ def restore_transaction_record_state(force_restore_state = false)
423
+ if restore_state = @_start_transaction_state
424
+ if force_restore_state || restore_state[:level] <= 1
440
425
  @new_record = restore_state[:new_record]
441
426
  @destroyed = restore_state[:destroyed]
442
- pk = self.class.primary_key
443
- if pk && _read_attribute(pk) != restore_state[:id]
444
- _write_attribute(pk, restore_state[:id])
427
+ @attributes = restore_state[:attributes].map do |attr|
428
+ value = @attributes.fetch_value(attr.name)
429
+ attr = attr.with_value_from_user(value) if attr.value != value
430
+ attr
431
+ end
432
+ @mutations_from_database = nil
433
+ @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])
445
436
  end
446
437
  freeze if restore_state[:frozen?]
447
438
  end
@@ -462,8 +453,10 @@ module ActiveRecord
462
453
  end
463
454
  end
464
455
 
465
- def set_transaction_state(state)
466
- @transaction_state = state
456
+ # Add the record to the current transaction so that the #after_rollback and #after_commit
457
+ # callbacks can be called.
458
+ def add_to_transaction
459
+ self.class.connection.add_transaction_record(self)
467
460
  end
468
461
 
469
462
  def has_transactional_callbacks?
@@ -483,19 +476,17 @@ module ActiveRecord
483
476
  # This method checks to see if the ActiveRecord object's state reflects
484
477
  # the TransactionState, and rolls back or commits the Active Record object
485
478
  # as appropriate.
486
- #
487
- # Since Active Record objects can be inside multiple transactions, this
488
- # method recursively goes through the parent of the TransactionState and
489
- # checks if the Active Record object reflects the state of the object.
490
479
  def sync_with_transaction_state
491
- update_attributes_from_transaction_state(@transaction_state)
492
- end
493
-
494
- def update_attributes_from_transaction_state(transaction_state)
495
- if transaction_state && transaction_state.finalized?
496
- restore_transaction_record_state(transaction_state.fully_rolledback?) if transaction_state.rolledback?
497
- force_clear_transaction_record_state if transaction_state.fully_committed?
498
- clear_transaction_record_state if transaction_state.fully_completed?
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
499
490
  end
500
491
  end
501
492
  end
@@ -10,7 +10,7 @@ module ActiveRecord
10
10
  classes = [klass]
11
11
  return classes if klass == ActiveRecord::Base
12
12
 
13
- while klass != klass.base_class
13
+ while !klass.base_class?
14
14
  classes << klass = klass.superclass
15
15
  end
16
16
  classes
@@ -47,13 +47,11 @@ module ActiveRecord
47
47
  end
48
48
 
49
49
  private
50
-
51
- def current_adapter_name
52
- ActiveRecord::Base.connection.adapter_name.downcase.to_sym
53
- end
50
+ def current_adapter_name
51
+ ActiveRecord::Base.connection.adapter_name.downcase.to_sym
52
+ end
54
53
  end
55
54
 
56
- Helpers = ActiveModel::Type::Helpers
57
55
  BigInteger = ActiveModel::Type::BigInteger
58
56
  Binary = ActiveModel::Type::Binary
59
57
  Boolean = ActiveModel::Type::Boolean
@@ -11,14 +11,13 @@ module ActiveRecord
11
11
  end
12
12
 
13
13
  private
14
-
15
14
  def registration_klass
16
15
  Registration
17
16
  end
18
17
 
19
- def find_registration(symbol, *args)
18
+ def find_registration(symbol, *args, **kwargs)
20
19
  registrations
21
- .select { |registration| registration.matches?(symbol, *args) }
20
+ .select { |registration| registration.matches?(symbol, *args, **kwargs) }
22
21
  .max
23
22
  end
24
23
  end
@@ -52,10 +51,7 @@ module ActiveRecord
52
51
  priority <=> other.priority
53
52
  end
54
53
 
55
- # TODO Change this to private once we've dropped Ruby 2.2 support.
56
- # Workaround for Ruby 2.2 "private attribute?" warning.
57
54
  protected
58
-
59
55
  attr_reader :name, :block, :adapter, :override
60
56
 
61
57
  def priority
@@ -74,7 +70,6 @@ module ActiveRecord
74
70
  end
75
71
 
76
72
  private
77
-
78
73
  def matches_adapter?(adapter: nil, **)
79
74
  (self.adapter.nil? || adapter == self.adapter)
80
75
  end
@@ -114,13 +109,8 @@ module ActiveRecord
114
109
  super | 4
115
110
  end
116
111
 
117
- # TODO Change this to private once we've dropped Ruby 2.2 support.
118
- # Workaround for Ruby 2.2 "private attribute?" warning.
119
- protected
120
-
121
- attr_reader :options, :klass
122
-
123
112
  private
113
+ attr_reader :options, :klass
124
114
 
125
115
  def matches_options?(**kwargs)
126
116
  options.all? do |key, value|
@@ -16,7 +16,6 @@ module ActiveRecord
16
16
  end
17
17
 
18
18
  private
19
-
20
19
  def perform_fetch(type, *args, &block)
21
20
  @mapping.fetch(type, block).call(type, *args)
22
21
  end
@@ -56,7 +56,6 @@ module ActiveRecord
56
56
  end
57
57
 
58
58
  private
59
-
60
59
  def default_value?(value)
61
60
  value == coder.load(nil)
62
61
  end
@@ -45,7 +45,6 @@ module ActiveRecord
45
45
  end
46
46
 
47
47
  private
48
-
49
48
  def perform_fetch(lookup_key, *args)
50
49
  matching_pair = @mapping.reverse_each.detect do |key, _|
51
50
  key === lookup_key
@@ -4,7 +4,6 @@ module ActiveRecord
4
4
  module Type
5
5
  class UnsignedInteger < ActiveModel::Type::Integer # :nodoc:
6
6
  private
7
-
8
7
  def max_value
9
8
  super * 2
10
9
  end
@@ -8,26 +8,27 @@ module ActiveRecord
8
8
  @table_name = table_name
9
9
  end
10
10
 
11
- def type_cast_for_database(attribute_name, value)
11
+ def type_cast_for_database(attr_name, value)
12
12
  return value if value.is_a?(Arel::Nodes::BindParam)
13
- column = column_for(attribute_name)
14
- connection.type_cast_from_column(column, value)
13
+ type = type_for_attribute(attr_name)
14
+ type.serialize(value)
15
15
  end
16
16
 
17
- # TODO Change this to private once we've dropped Ruby 2.2 support.
18
- # Workaround for Ruby 2.2 "private attribute?" warning.
19
- protected
17
+ def type_for_attribute(attr_name)
18
+ schema_cache = connection.schema_cache
20
19
 
21
- attr_reader :table_name
22
- delegate :connection, to: :@klass
20
+ if schema_cache.data_source_exists?(table_name)
21
+ column = schema_cache.columns_hash(table_name)[attr_name.to_s]
22
+ type = connection.lookup_cast_type_from_column(column) if column
23
+ end
23
24
 
24
- private
25
+ type || Type.default_value
26
+ end
25
27
 
26
- def column_for(attribute_name)
27
- if connection.schema_cache.data_source_exists?(table_name)
28
- connection.schema_cache.columns_hash(table_name)[attribute_name.to_s]
29
- end
30
- end
28
+ delegate :connection, to: :@klass, private: true
29
+
30
+ private
31
+ attr_reader :table_name
31
32
  end
32
33
  end
33
34
  end
@@ -13,10 +13,7 @@ module ActiveRecord
13
13
  type.serialize(value)
14
14
  end
15
15
 
16
- # TODO Change this to private once we've dropped Ruby 2.2 support.
17
- # Workaround for Ruby 2.2 "private attribute?" warning.
18
- protected
19
-
16
+ private
20
17
  attr_reader :types
21
18
  end
22
19
  end