activerecord 5.2.8.1 → 6.1.6.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 (316) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1255 -596
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +7 -5
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record/aggregations.rb +9 -8
  7. data/lib/active_record/association_relation.rb +30 -10
  8. data/lib/active_record/associations/alias_tracker.rb +19 -16
  9. data/lib/active_record/associations/association.rb +100 -41
  10. data/lib/active_record/associations/association_scope.rb +23 -21
  11. data/lib/active_record/associations/belongs_to_association.rb +55 -48
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -6
  13. data/lib/active_record/associations/builder/association.rb +45 -22
  14. data/lib/active_record/associations/builder/belongs_to.rb +29 -59
  15. data/lib/active_record/associations/builder/collection_association.rb +8 -17
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
  17. data/lib/active_record/associations/builder/has_many.rb +8 -2
  18. data/lib/active_record/associations/builder/has_one.rb +33 -2
  19. data/lib/active_record/associations/builder/singular_association.rb +3 -1
  20. data/lib/active_record/associations/collection_association.rb +44 -34
  21. data/lib/active_record/associations/collection_proxy.rb +25 -21
  22. data/lib/active_record/associations/foreign_association.rb +20 -0
  23. data/lib/active_record/associations/has_many_association.rb +26 -13
  24. data/lib/active_record/associations/has_many_through_association.rb +24 -18
  25. data/lib/active_record/associations/has_one_association.rb +43 -31
  26. data/lib/active_record/associations/has_one_through_association.rb +5 -5
  27. data/lib/active_record/associations/join_dependency/join_association.rb +44 -22
  28. data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
  29. data/lib/active_record/associations/join_dependency.rb +91 -60
  30. data/lib/active_record/associations/preloader/association.rb +69 -43
  31. data/lib/active_record/associations/preloader/through_association.rb +49 -40
  32. data/lib/active_record/associations/preloader.rb +47 -34
  33. data/lib/active_record/associations/singular_association.rb +3 -17
  34. data/lib/active_record/associations/through_association.rb +1 -1
  35. data/lib/active_record/associations.rb +137 -25
  36. data/lib/active_record/attribute_assignment.rb +17 -19
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -7
  38. data/lib/active_record/attribute_methods/dirty.rb +101 -40
  39. data/lib/active_record/attribute_methods/primary_key.rb +20 -25
  40. data/lib/active_record/attribute_methods/query.rb +4 -8
  41. data/lib/active_record/attribute_methods/read.rb +14 -56
  42. data/lib/active_record/attribute_methods/serialization.rb +12 -7
  43. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
  44. data/lib/active_record/attribute_methods/write.rb +18 -34
  45. data/lib/active_record/attribute_methods.rb +81 -143
  46. data/lib/active_record/attributes.rb +46 -9
  47. data/lib/active_record/autosave_association.rb +57 -42
  48. data/lib/active_record/base.rb +4 -17
  49. data/lib/active_record/callbacks.rb +158 -43
  50. data/lib/active_record/coders/yaml_column.rb +1 -2
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +272 -130
  52. data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -36
  53. data/lib/active_record/connection_adapters/abstract/database_statements.rb +167 -146
  54. data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -14
  55. data/lib/active_record/connection_adapters/abstract/quoting.rb +98 -47
  56. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  57. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -110
  58. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +211 -90
  59. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -4
  60. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +385 -144
  61. data/lib/active_record/connection_adapters/abstract/transaction.rb +167 -69
  62. data/lib/active_record/connection_adapters/abstract_adapter.rb +229 -99
  63. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +243 -275
  64. data/lib/active_record/connection_adapters/column.rb +30 -12
  65. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  66. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  67. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  68. data/lib/active_record/connection_adapters/mysql/database_statements.rb +88 -32
  69. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  70. data/lib/active_record/connection_adapters/mysql/quoting.rb +59 -7
  71. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
  72. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
  73. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +18 -7
  74. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +142 -19
  75. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
  76. data/lib/active_record/connection_adapters/mysql2_adapter.rb +53 -18
  77. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  78. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  79. data/lib/active_record/connection_adapters/postgresql/column.rb +37 -28
  80. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +40 -54
  81. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  82. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  83. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  84. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
  90. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
  93. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
  94. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  95. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
  96. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
  97. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  98. data/lib/active_record/connection_adapters/postgresql/quoting.rb +47 -10
  99. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
  100. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +19 -4
  101. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
  102. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  103. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +120 -100
  104. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
  105. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  106. data/lib/active_record/connection_adapters/postgresql_adapter.rb +224 -120
  107. data/lib/active_record/connection_adapters/schema_cache.rb +159 -21
  108. data/lib/active_record/connection_adapters/sql_type_metadata.rb +17 -6
  109. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -0
  110. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
  111. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  112. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +77 -13
  113. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +174 -186
  114. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  115. data/lib/active_record/connection_adapters.rb +52 -0
  116. data/lib/active_record/connection_handling.rb +293 -33
  117. data/lib/active_record/core.rb +333 -98
  118. data/lib/active_record/counter_cache.rb +8 -30
  119. data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
  120. data/lib/active_record/database_configurations/database_config.rb +80 -0
  121. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  122. data/lib/active_record/database_configurations/url_config.rb +53 -0
  123. data/lib/active_record/database_configurations.rb +273 -0
  124. data/lib/active_record/delegated_type.rb +209 -0
  125. data/lib/active_record/destroy_association_async_job.rb +36 -0
  126. data/lib/active_record/dynamic_matchers.rb +3 -4
  127. data/lib/active_record/enum.rb +108 -36
  128. data/lib/active_record/errors.rb +62 -19
  129. data/lib/active_record/explain.rb +10 -6
  130. data/lib/active_record/explain_subscriber.rb +1 -1
  131. data/lib/active_record/fixture_set/file.rb +10 -17
  132. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  133. data/lib/active_record/fixture_set/render_context.rb +17 -0
  134. data/lib/active_record/fixture_set/table_row.rb +152 -0
  135. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  136. data/lib/active_record/fixtures.rb +200 -481
  137. data/lib/active_record/gem_version.rb +3 -3
  138. data/lib/active_record/inheritance.rb +53 -24
  139. data/lib/active_record/insert_all.rb +212 -0
  140. data/lib/active_record/integration.rb +67 -17
  141. data/lib/active_record/internal_metadata.rb +28 -9
  142. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  143. data/lib/active_record/locking/optimistic.rb +37 -23
  144. data/lib/active_record/locking/pessimistic.rb +9 -5
  145. data/lib/active_record/log_subscriber.rb +35 -35
  146. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  147. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  148. data/lib/active_record/middleware/database_selector.rb +77 -0
  149. data/lib/active_record/migration/command_recorder.rb +96 -44
  150. data/lib/active_record/migration/compatibility.rb +145 -64
  151. data/lib/active_record/migration/join_table.rb +0 -1
  152. data/lib/active_record/migration.rb +206 -157
  153. data/lib/active_record/model_schema.rb +148 -22
  154. data/lib/active_record/nested_attributes.rb +4 -7
  155. data/lib/active_record/no_touching.rb +8 -1
  156. data/lib/active_record/null_relation.rb +0 -1
  157. data/lib/active_record/persistence.rb +267 -59
  158. data/lib/active_record/query_cache.rb +21 -4
  159. data/lib/active_record/querying.rb +40 -23
  160. data/lib/active_record/railtie.rb +116 -59
  161. data/lib/active_record/railties/console_sandbox.rb +2 -4
  162. data/lib/active_record/railties/controller_runtime.rb +30 -35
  163. data/lib/active_record/railties/databases.rake +411 -80
  164. data/lib/active_record/readonly_attributes.rb +4 -0
  165. data/lib/active_record/reflection.rb +109 -93
  166. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  167. data/lib/active_record/relation/batches.rb +44 -35
  168. data/lib/active_record/relation/calculations.rb +157 -90
  169. data/lib/active_record/relation/delegation.rb +35 -50
  170. data/lib/active_record/relation/finder_methods.rb +64 -39
  171. data/lib/active_record/relation/from_clause.rb +5 -1
  172. data/lib/active_record/relation/merger.rb +32 -40
  173. data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
  174. data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
  175. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  176. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +11 -10
  177. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  178. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  179. data/lib/active_record/relation/predicate_builder.rb +62 -45
  180. data/lib/active_record/relation/query_attribute.rb +13 -8
  181. data/lib/active_record/relation/query_methods.rb +476 -187
  182. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  183. data/lib/active_record/relation/spawn_methods.rb +9 -9
  184. data/lib/active_record/relation/where_clause.rb +115 -62
  185. data/lib/active_record/relation.rb +379 -115
  186. data/lib/active_record/result.rb +64 -38
  187. data/lib/active_record/runtime_registry.rb +2 -2
  188. data/lib/active_record/sanitization.rb +22 -41
  189. data/lib/active_record/schema.rb +2 -11
  190. data/lib/active_record/schema_dumper.rb +54 -9
  191. data/lib/active_record/schema_migration.rb +7 -9
  192. data/lib/active_record/scoping/default.rb +4 -8
  193. data/lib/active_record/scoping/named.rb +17 -24
  194. data/lib/active_record/scoping.rb +8 -9
  195. data/lib/active_record/secure_token.rb +16 -8
  196. data/lib/active_record/serialization.rb +5 -3
  197. data/lib/active_record/signed_id.rb +116 -0
  198. data/lib/active_record/statement_cache.rb +49 -6
  199. data/lib/active_record/store.rb +88 -9
  200. data/lib/active_record/suppressor.rb +2 -2
  201. data/lib/active_record/table_metadata.rb +42 -43
  202. data/lib/active_record/tasks/database_tasks.rb +277 -81
  203. data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
  204. data/lib/active_record/tasks/postgresql_database_tasks.rb +27 -32
  205. data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
  206. data/lib/active_record/test_databases.rb +24 -0
  207. data/lib/active_record/test_fixtures.rb +287 -0
  208. data/lib/active_record/timestamp.rb +43 -32
  209. data/lib/active_record/touch_later.rb +23 -22
  210. data/lib/active_record/transactions.rb +62 -118
  211. data/lib/active_record/translation.rb +1 -1
  212. data/lib/active_record/type/adapter_specific_registry.rb +3 -13
  213. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  214. data/lib/active_record/type/serialized.rb +6 -3
  215. data/lib/active_record/type/time.rb +10 -0
  216. data/lib/active_record/type/type_map.rb +0 -1
  217. data/lib/active_record/type/unsigned_integer.rb +0 -1
  218. data/lib/active_record/type.rb +10 -5
  219. data/lib/active_record/type_caster/connection.rb +15 -15
  220. data/lib/active_record/type_caster/map.rb +8 -8
  221. data/lib/active_record/validations/associated.rb +1 -2
  222. data/lib/active_record/validations/numericality.rb +35 -0
  223. data/lib/active_record/validations/uniqueness.rb +38 -30
  224. data/lib/active_record/validations.rb +4 -3
  225. data/lib/active_record.rb +13 -12
  226. data/lib/arel/alias_predication.rb +9 -0
  227. data/lib/arel/attributes/attribute.rb +41 -0
  228. data/lib/arel/collectors/bind.rb +29 -0
  229. data/lib/arel/collectors/composite.rb +39 -0
  230. data/lib/arel/collectors/plain_string.rb +20 -0
  231. data/lib/arel/collectors/sql_string.rb +27 -0
  232. data/lib/arel/collectors/substitute_binds.rb +35 -0
  233. data/lib/arel/crud.rb +42 -0
  234. data/lib/arel/delete_manager.rb +18 -0
  235. data/lib/arel/errors.rb +9 -0
  236. data/lib/arel/expressions.rb +29 -0
  237. data/lib/arel/factory_methods.rb +49 -0
  238. data/lib/arel/insert_manager.rb +49 -0
  239. data/lib/arel/math.rb +45 -0
  240. data/lib/arel/nodes/and.rb +32 -0
  241. data/lib/arel/nodes/ascending.rb +23 -0
  242. data/lib/arel/nodes/binary.rb +126 -0
  243. data/lib/arel/nodes/bind_param.rb +44 -0
  244. data/lib/arel/nodes/case.rb +55 -0
  245. data/lib/arel/nodes/casted.rb +62 -0
  246. data/lib/arel/nodes/comment.rb +29 -0
  247. data/lib/arel/nodes/count.rb +12 -0
  248. data/lib/arel/nodes/delete_statement.rb +45 -0
  249. data/lib/arel/nodes/descending.rb +23 -0
  250. data/lib/arel/nodes/equality.rb +15 -0
  251. data/lib/arel/nodes/extract.rb +24 -0
  252. data/lib/arel/nodes/false.rb +16 -0
  253. data/lib/arel/nodes/full_outer_join.rb +8 -0
  254. data/lib/arel/nodes/function.rb +44 -0
  255. data/lib/arel/nodes/grouping.rb +11 -0
  256. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  257. data/lib/arel/nodes/in.rb +15 -0
  258. data/lib/arel/nodes/infix_operation.rb +92 -0
  259. data/lib/arel/nodes/inner_join.rb +8 -0
  260. data/lib/arel/nodes/insert_statement.rb +37 -0
  261. data/lib/arel/nodes/join_source.rb +20 -0
  262. data/lib/arel/nodes/matches.rb +18 -0
  263. data/lib/arel/nodes/named_function.rb +23 -0
  264. data/lib/arel/nodes/node.rb +51 -0
  265. data/lib/arel/nodes/node_expression.rb +13 -0
  266. data/lib/arel/nodes/ordering.rb +27 -0
  267. data/lib/arel/nodes/outer_join.rb +8 -0
  268. data/lib/arel/nodes/over.rb +15 -0
  269. data/lib/arel/nodes/regexp.rb +16 -0
  270. data/lib/arel/nodes/right_outer_join.rb +8 -0
  271. data/lib/arel/nodes/select_core.rb +67 -0
  272. data/lib/arel/nodes/select_statement.rb +41 -0
  273. data/lib/arel/nodes/sql_literal.rb +19 -0
  274. data/lib/arel/nodes/string_join.rb +11 -0
  275. data/lib/arel/nodes/table_alias.rb +31 -0
  276. data/lib/arel/nodes/terminal.rb +16 -0
  277. data/lib/arel/nodes/true.rb +16 -0
  278. data/lib/arel/nodes/unary.rb +44 -0
  279. data/lib/arel/nodes/unary_operation.rb +20 -0
  280. data/lib/arel/nodes/unqualified_column.rb +22 -0
  281. data/lib/arel/nodes/update_statement.rb +41 -0
  282. data/lib/arel/nodes/values_list.rb +9 -0
  283. data/lib/arel/nodes/window.rb +126 -0
  284. data/lib/arel/nodes/with.rb +11 -0
  285. data/lib/arel/nodes.rb +70 -0
  286. data/lib/arel/order_predications.rb +13 -0
  287. data/lib/arel/predications.rb +250 -0
  288. data/lib/arel/select_manager.rb +270 -0
  289. data/lib/arel/table.rb +118 -0
  290. data/lib/arel/tree_manager.rb +72 -0
  291. data/lib/arel/update_manager.rb +34 -0
  292. data/lib/arel/visitors/dot.rb +308 -0
  293. data/lib/arel/visitors/mysql.rb +93 -0
  294. data/lib/arel/visitors/postgresql.rb +120 -0
  295. data/lib/arel/visitors/sqlite.rb +38 -0
  296. data/lib/arel/visitors/to_sql.rb +899 -0
  297. data/lib/arel/visitors/visitor.rb +45 -0
  298. data/lib/arel/visitors.rb +13 -0
  299. data/lib/arel/window_predications.rb +9 -0
  300. data/lib/arel.rb +54 -0
  301. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  302. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
  303. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
  304. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
  305. data/lib/rails/generators/active_record/migration.rb +19 -2
  306. data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
  307. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  308. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  309. metadata +116 -30
  310. data/lib/active_record/attribute_decorators.rb +0 -90
  311. data/lib/active_record/collection_cache_key.rb +0 -53
  312. data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
  313. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
  314. data/lib/active_record/define_callbacks.rb +0 -22
  315. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
  316. data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -2,27 +2,26 @@
2
2
 
3
3
  module ActiveRecord
4
4
  # = Active Record Touch Later
5
- module TouchLater
6
- extend ActiveSupport::Concern
7
-
8
- included do
9
- before_commit_without_transaction_enrollment :touch_deferred_attributes
5
+ module TouchLater # :nodoc:
6
+ def before_committed!
7
+ touch_deferred_attributes if has_defer_touch_attrs? && persisted?
8
+ super
10
9
  end
11
10
 
12
11
  def touch_later(*names) # :nodoc:
13
- unless persisted?
14
- raise ActiveRecordError, <<-MSG.squish
15
- cannot touch on a new or destroyed record object. Consider using
16
- persisted?, new_record?, or destroyed? before touching
17
- MSG
18
- end
12
+ _raise_record_not_touched_error unless persisted?
19
13
 
20
14
  @_defer_touch_attrs ||= timestamp_attributes_for_update_in_model
21
- @_defer_touch_attrs |= names
15
+ @_defer_touch_attrs |= names.map! do |name|
16
+ name = name.to_s
17
+ self.class.attribute_aliases[name] || name
18
+ end unless names.empty?
19
+
22
20
  @_touch_time = current_time_from_proper_timezone
23
21
 
24
22
  surreptitiously_touch @_defer_touch_attrs
25
- self.class.connection.add_transaction_record self
23
+ add_to_transaction
24
+ @_new_record_before_last_commit ||= false
26
25
 
27
26
  # touch the parents as we are not calling the after_save callbacks
28
27
  self.class.reflect_on_all_associations(:belongs_to).each do |r|
@@ -35,22 +34,24 @@ module ActiveRecord
35
34
  def touch(*names, time: nil) # :nodoc:
36
35
  if has_defer_touch_attrs?
37
36
  names |= @_defer_touch_attrs
37
+ super(*names, time: time)
38
+ @_defer_touch_attrs, @_touch_time = nil, nil
39
+ else
40
+ super
38
41
  end
39
- super(*names, time: time)
40
42
  end
41
43
 
42
44
  private
43
-
44
- def surreptitiously_touch(attrs)
45
- attrs.each { |attr| write_attribute attr, @_touch_time }
46
- clear_attribute_changes attrs
45
+ def surreptitiously_touch(attr_names)
46
+ attr_names.each do |attr_name|
47
+ _write_attribute(attr_name, @_touch_time)
48
+ clear_attribute_change(attr_name)
49
+ end
47
50
  end
48
51
 
49
52
  def touch_deferred_attributes
50
- if has_defer_touch_attrs? && persisted?
51
- touch(*@_defer_touch_attrs, time: @_touch_time)
52
- @_defer_touch_attrs, @_touch_time = nil, nil
53
- end
53
+ @_skip_dirty_tracking = true
54
+ touch(time: @_touch_time)
54
55
  end
55
56
 
56
57
  def has_defer_touch_attrs?
@@ -10,9 +10,6 @@ module ActiveRecord
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
 
@@ -164,13 +161,13 @@ module ActiveRecord
164
161
  # end
165
162
  # end
166
163
  #
167
- # only "Kotori" is created. This works on MySQL and PostgreSQL. SQLite3 version >= '3.6.8' also supports it.
164
+ # only "Kotori" is created.
168
165
  #
169
166
  # Most databases don't support true nested transactions. At the time of
170
167
  # writing, the only database that we're aware of that supports true nested
171
168
  # 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
169
+ # transactions by using savepoints. See
170
+ # https://dev.mysql.com/doc/refman/en/savepoint.html
174
171
  # for more information about savepoints.
175
172
  #
176
173
  # === \Callbacks
@@ -208,8 +205,8 @@ module ActiveRecord
208
205
  # Note that "TRUNCATE" is also a MySQL DDL statement!
209
206
  module ClassMethods
210
207
  # See the ConnectionAdapters::DatabaseStatements#transaction API docs.
211
- def transaction(options = {}, &block)
212
- connection.transaction(options, &block)
208
+ def transaction(**options, &block)
209
+ connection.transaction(**options, &block)
213
210
  end
214
211
 
215
212
  def before_commit(*args, &block) # :nodoc:
@@ -234,6 +231,12 @@ module ActiveRecord
234
231
  set_callback(:commit, :after, *args, &block)
235
232
  end
236
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
+
237
240
  # Shortcut for <tt>after_commit :hook, on: :create</tt>.
238
241
  def after_create_commit(*args, &block)
239
242
  set_options_for_callbacks!(args, on: :create)
@@ -260,23 +263,7 @@ module ActiveRecord
260
263
  set_callback(:rollback, :after, *args, &block)
261
264
  end
262
265
 
263
- def before_commit_without_transaction_enrollment(*args, &block) # :nodoc:
264
- set_options_for_callbacks!(args)
265
- set_callback(:before_commit_without_transaction_enrollment, :before, *args, &block)
266
- end
267
-
268
- def after_commit_without_transaction_enrollment(*args, &block) # :nodoc:
269
- set_options_for_callbacks!(args)
270
- set_callback(:commit_without_transaction_enrollment, :after, *args, &block)
271
- end
272
-
273
- def after_rollback_without_transaction_enrollment(*args, &block) # :nodoc:
274
- set_options_for_callbacks!(args)
275
- set_callback(:rollback_without_transaction_enrollment, :after, *args, &block)
276
- end
277
-
278
266
  private
279
-
280
267
  def set_options_for_callbacks!(args, enforced_options = {})
281
268
  options = args.extract_options!.merge!(enforced_options)
282
269
  args << options
@@ -284,8 +271,10 @@ module ActiveRecord
284
271
  if options[:on]
285
272
  fire_on = Array(options[:on])
286
273
  assert_valid_transaction_action(fire_on)
287
- options[:if] = Array(options[:if])
288
- options[:if].unshift(-> { transaction_include_any_action?(fire_on) })
274
+ options[:if] = [
275
+ -> { transaction_include_any_action?(fire_on) },
276
+ *options[:if]
277
+ ]
289
278
  end
290
279
  end
291
280
 
@@ -297,41 +286,27 @@ module ActiveRecord
297
286
  end
298
287
 
299
288
  # See ActiveRecord::Transactions::ClassMethods for detailed documentation.
300
- def transaction(options = {}, &block)
301
- self.class.transaction(options, &block)
289
+ def transaction(**options, &block)
290
+ self.class.transaction(**options, &block)
302
291
  end
303
292
 
304
293
  def destroy #:nodoc:
305
294
  with_transaction_returning_status { super }
306
295
  end
307
296
 
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:
297
+ def save(**) #:nodoc:
315
298
  with_transaction_returning_status { super }
316
299
  end
317
300
 
318
- def touch(*) #:nodoc:
301
+ def save!(**) #:nodoc:
319
302
  with_transaction_returning_status { super }
320
303
  end
321
304
 
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
305
+ def touch(*, **) #:nodoc:
306
+ with_transaction_returning_status { super }
331
307
  end
332
308
 
333
309
  def before_committed! # :nodoc:
334
- _run_before_commit_without_transaction_enrollment_callbacks
335
310
  _run_before_commit_callbacks
336
311
  end
337
312
 
@@ -341,13 +316,12 @@ module ActiveRecord
341
316
  # but call it after the commit of a destroyed object.
342
317
  def committed!(should_run_callbacks: true) #:nodoc:
343
318
  force_clear_transaction_record_state
344
- if should_run_callbacks && (destroyed? || persisted?)
319
+ if should_run_callbacks
345
320
  @_committed_already_called = true
346
- _run_commit_without_transaction_enrollment_callbacks
347
321
  _run_commit_callbacks
348
322
  end
349
323
  ensure
350
- @_committed_already_called = false
324
+ @_committed_already_called = @_trigger_update_callback = @_trigger_destroy_callback = false
351
325
  end
352
326
 
353
327
  # Call the #after_rollback callbacks. The +force_restore_state+ argument indicates if the record
@@ -355,23 +329,11 @@ module ActiveRecord
355
329
  def rolledback!(force_restore_state: false, should_run_callbacks: true) #:nodoc:
356
330
  if should_run_callbacks
357
331
  _run_rollback_callbacks
358
- _run_rollback_without_transaction_enrollment_callbacks
359
332
  end
360
333
  ensure
361
334
  restore_transaction_record_state(force_restore_state)
362
335
  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
336
+ @_trigger_update_callback = @_trigger_destroy_callback = false if force_restore_state
375
337
  end
376
338
 
377
339
  # Executes +method+ within a transaction and captures its return value as a
@@ -382,36 +344,40 @@ module ActiveRecord
382
344
  # instance.
383
345
  def with_transaction_returning_status
384
346
  status = nil
385
- self.class.transaction do
386
- add_to_transaction
347
+ connection = self.class.connection
348
+ ensure_finalize = !connection.transaction_open?
349
+
350
+ connection.transaction do
351
+ add_to_transaction(ensure_finalize || has_transactional_callbacks?)
352
+ remember_transaction_record_state
353
+
387
354
  status = yield
388
355
  raise ActiveRecord::Rollback unless status
389
356
  end
390
357
  status
391
- ensure
392
- if @transaction_state && @transaction_state.committed?
393
- clear_transaction_record_state
394
- end
395
358
  end
396
359
 
397
- protected
398
- attr_reader :_committed_already_called, :_trigger_update_callback, :_trigger_destroy_callback
360
+ def trigger_transactional_callbacks? # :nodoc:
361
+ (@_new_record_before_last_commit || _trigger_update_callback) && persisted? ||
362
+ _trigger_destroy_callback && destroyed?
363
+ end
399
364
 
400
365
  private
366
+ attr_reader :_committed_already_called, :_trigger_update_callback, :_trigger_destroy_callback
401
367
 
402
368
  # Save the new record state and id of a record so it can be restored later if a transaction fails.
403
369
  def remember_transaction_record_state
404
- @_start_transaction_state.reverse_merge!(
370
+ @_start_transaction_state ||= {
405
371
  id: id,
406
372
  new_record: @new_record,
373
+ previously_new_record: @previously_new_record,
407
374
  destroyed: @destroyed,
375
+ attributes: @attributes,
408
376
  frozen?: frozen?,
409
- )
410
- @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) + 1
411
- remember_new_record_before_last_commit
412
- end
377
+ level: 0
378
+ }
379
+ @_start_transaction_state[:level] += 1
413
380
 
414
- def remember_new_record_before_last_commit
415
381
  if _committed_already_called
416
382
  @_new_record_before_last_commit = false
417
383
  else
@@ -421,27 +387,32 @@ module ActiveRecord
421
387
 
422
388
  # Clear the new record state and id of a record.
423
389
  def clear_transaction_record_state
424
- @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1
390
+ return unless @_start_transaction_state
391
+ @_start_transaction_state[:level] -= 1
425
392
  force_clear_transaction_record_state if @_start_transaction_state[:level] < 1
426
393
  end
427
394
 
428
395
  # Force to clear the transaction record state.
429
396
  def force_clear_transaction_record_state
430
- @_start_transaction_state.clear
397
+ @_start_transaction_state = nil
431
398
  end
432
399
 
433
400
  # 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
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
440
404
  @new_record = restore_state[:new_record]
405
+ @previously_new_record = restore_state[:previously_new_record]
441
406
  @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])
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])
445
416
  end
446
417
  freeze if restore_state[:frozen?]
447
418
  end
@@ -462,41 +433,14 @@ module ActiveRecord
462
433
  end
463
434
  end
464
435
 
465
- def set_transaction_state(state)
466
- @transaction_state = state
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)
467
440
  end
468
441
 
469
442
  def has_transactional_callbacks?
470
443
  !_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_before_commit_callbacks.empty?
471
444
  end
472
-
473
- # Updates the attributes on this particular Active Record object so that
474
- # if it's associated with a transaction, then the state of the Active Record
475
- # object will be updated to reflect the current state of the transaction.
476
- #
477
- # The <tt>@transaction_state</tt> variable stores the states of the associated
478
- # transaction. This relies on the fact that a transaction can only be in
479
- # one rollback or commit (otherwise a list of states would be required).
480
- # Each Active Record object inside of a transaction carries that transaction's
481
- # TransactionState.
482
- #
483
- # This method checks to see if the ActiveRecord object's state reflects
484
- # the TransactionState, and rolls back or commits the Active Record object
485
- # 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
- 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?
499
- end
500
- end
501
445
  end
502
446
  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
@@ -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,15 +56,18 @@ 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
63
62
 
64
63
  def encoded(value)
65
- unless default_value?(value)
66
- coder.dump(value)
64
+ return if default_value?(value)
65
+ payload = coder.dump(value)
66
+ if payload && binary? && payload.encoding != Encoding::BINARY
67
+ payload = payload.dup if payload.frozen?
68
+ payload.force_encoding(Encoding::BINARY)
67
69
  end
70
+ payload
68
71
  end
69
72
  end
70
73
  end
@@ -16,6 +16,16 @@ module ActiveRecord
16
16
  value
17
17
  end
18
18
  end
19
+
20
+ private
21
+ def cast_value(value)
22
+ case value = super
23
+ when Value
24
+ value.__getobj__
25
+ else
26
+ value
27
+ end
28
+ end
19
29
  end
20
30
  end
21
31
  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
@@ -46,20 +46,24 @@ module ActiveRecord
46
46
  @default_value ||= Value.new
47
47
  end
48
48
 
49
- private
50
-
51
- def current_adapter_name
52
- ActiveRecord::Base.connection.adapter_name.downcase.to_sym
49
+ def adapter_name_from(model) # :nodoc:
50
+ # TODO: this shouldn't depend on a connection to the database
51
+ model.connection.adapter_name.downcase.to_sym
53
52
  end
53
+
54
+ private
55
+ def current_adapter_name
56
+ adapter_name_from(ActiveRecord::Base)
57
+ end
54
58
  end
55
59
 
56
- Helpers = ActiveModel::Type::Helpers
57
60
  BigInteger = ActiveModel::Type::BigInteger
58
61
  Binary = ActiveModel::Type::Binary
59
62
  Boolean = ActiveModel::Type::Boolean
60
63
  Decimal = ActiveModel::Type::Decimal
61
64
  Float = ActiveModel::Type::Float
62
65
  Integer = ActiveModel::Type::Integer
66
+ ImmutableString = ActiveModel::Type::ImmutableString
63
67
  String = ActiveModel::Type::String
64
68
  Value = ActiveModel::Type::Value
65
69
 
@@ -71,6 +75,7 @@ module ActiveRecord
71
75
  register(:decimal, Type::Decimal, override: false)
72
76
  register(:float, Type::Float, override: false)
73
77
  register(:integer, Type::Integer, override: false)
78
+ register(:immutable_string, Type::ImmutableString, override: false)
74
79
  register(:json, Type::Json, override: false)
75
80
  register(:string, Type::String, override: false)
76
81
  register(:text, Type::Text, override: false)
@@ -8,26 +8,26 @@ module ActiveRecord
8
8
  @table_name = table_name
9
9
  end
10
10
 
11
- def type_cast_for_database(attribute_name, value)
12
- return value if value.is_a?(Arel::Nodes::BindParam)
13
- column = column_for(attribute_name)
14
- connection.type_cast_from_column(column, value)
11
+ def type_cast_for_database(attr_name, value)
12
+ type = type_for_attribute(attr_name)
13
+ type.serialize(value)
15
14
  end
16
15
 
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
16
+ def type_for_attribute(attr_name)
17
+ schema_cache = connection.schema_cache
20
18
 
21
- attr_reader :table_name
22
- delegate :connection, to: :@klass
19
+ if schema_cache.data_source_exists?(table_name)
20
+ column = schema_cache.columns_hash(table_name)[attr_name.to_s]
21
+ type = connection.lookup_cast_type_from_column(column) if column
22
+ end
23
23
 
24
- private
24
+ type || Type.default_value
25
+ end
25
26
 
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
27
+ delegate :connection, to: :@klass, private: true
28
+
29
+ private
30
+ attr_reader :table_name
31
31
  end
32
32
  end
33
33
  end
@@ -3,21 +3,21 @@
3
3
  module ActiveRecord
4
4
  module TypeCaster
5
5
  class Map # :nodoc:
6
- def initialize(types)
7
- @types = types
6
+ def initialize(klass)
7
+ @klass = klass
8
8
  end
9
9
 
10
10
  def type_cast_for_database(attr_name, value)
11
- return value if value.is_a?(Arel::Nodes::BindParam)
12
- type = types.type_for_attribute(attr_name)
11
+ type = type_for_attribute(attr_name)
13
12
  type.serialize(value)
14
13
  end
15
14
 
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
15
+ def type_for_attribute(name)
16
+ klass.type_for_attribute(name)
17
+ end
19
18
 
20
- attr_reader :types
19
+ private
20
+ attr_reader :klass
21
21
  end
22
22
  end
23
23
  end
@@ -5,12 +5,11 @@ module ActiveRecord
5
5
  class AssociatedValidator < ActiveModel::EachValidator #:nodoc:
6
6
  def validate_each(record, attribute, value)
7
7
  if Array(value).reject { |r| valid_object?(r) }.any?
8
- record.errors.add(attribute, :invalid, options.merge(value: value))
8
+ record.errors.add(attribute, :invalid, **options.merge(value: value))
9
9
  end
10
10
  end
11
11
 
12
12
  private
13
-
14
13
  def valid_object?(record)
15
14
  (record.respond_to?(:marked_for_destruction?) && record.marked_for_destruction?) || record.valid?
16
15
  end