activerecord 5.2.8.1 → 6.1.7.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (316) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1347 -624
  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 +16 -7
  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 +107 -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 +73 -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 +225 -121
  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 +341 -99
  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 +4 -4
  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 +113 -74
  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 +478 -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 +94 -10
  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 +291 -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 +118 -32
  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
@@ -29,9 +29,9 @@ module ActiveRecord
29
29
  # == Callbacks
30
30
  #
31
31
  # Association with autosave option defines several callbacks on your
32
- # model (before_save, after_create, after_update). Please note that
32
+ # model (around_save, before_save, after_create, after_update). Please note that
33
33
  # callbacks are executed in the order they were defined in
34
- # model. You should avoid modifying the association content, before
34
+ # model. You should avoid modifying the association content before
35
35
  # autosave callbacks are executed. Placing your callbacks after
36
36
  # associations is usually a good practice.
37
37
  #
@@ -91,8 +91,9 @@ module ActiveRecord
91
91
  # post.save # => saves both post and comment
92
92
  #
93
93
  # post = Post.create(title: 'ruby rocks')
94
- # post.comments.create(body: 'hello world')
95
- # post.save # => saves both post and comment
94
+ # comment = post.comments.create(body: 'hello world')
95
+ # comment.body = 'hi everyone'
96
+ # post.save # => saves post, but not comment
96
97
  #
97
98
  # When <tt>:autosave</tt> is true all children are saved, no matter whether they
98
99
  # are new records or not:
@@ -102,11 +103,10 @@ module ActiveRecord
102
103
  # end
103
104
  #
104
105
  # post = Post.create(title: 'ruby rocks')
105
- # post.comments.create(body: 'hello world')
106
- # post.comments[0].body = 'hi everyone'
106
+ # comment = post.comments.create(body: 'hello world')
107
+ # comment.body = 'hi everyone'
107
108
  # post.comments.build(body: "good morning.")
108
- # post.title += "!"
109
- # post.save # => saves both post and comments.
109
+ # post.save # => saves post and both comments.
110
110
  #
111
111
  # Destroying one of the associated models as part of the parent's save action
112
112
  # is as simple as marking it for destruction:
@@ -127,6 +127,14 @@ module ActiveRecord
127
127
  # Now it _is_ removed from the database:
128
128
  #
129
129
  # Comment.find_by(id: id).nil? # => true
130
+ #
131
+ # === Caveats
132
+ #
133
+ # Note that autosave will only trigger for already-persisted association records
134
+ # if the records themselves have been changed. This is to protect against
135
+ # <tt>SystemStackError</tt> caused by circular association validations. The one
136
+ # exception is if a custom validation context is used, in which case the validations
137
+ # will always fire on the associated records.
130
138
  module AutosaveAssociation
131
139
  extend ActiveSupport::Concern
132
140
 
@@ -147,9 +155,23 @@ module ActiveRecord
147
155
 
148
156
  module ClassMethods # :nodoc:
149
157
  private
158
+ if Module.method(:method_defined?).arity == 1 # MRI 2.5 and older
159
+ using Module.new {
160
+ refine Module do
161
+ def method_defined?(method, inherit = true)
162
+ if inherit
163
+ super(method)
164
+ else
165
+ instance_methods(false).include?(method.to_sym)
166
+ end
167
+ end
168
+ end
169
+ }
170
+ end
150
171
 
151
172
  def define_non_cyclic_method(name, &block)
152
- return if method_defined?(name)
173
+ return if method_defined?(name, false)
174
+
153
175
  define_method(name) do |*args|
154
176
  result = true; @_already_called ||= {}
155
177
  # Loop prevention for validation of associations
@@ -181,8 +203,7 @@ module ActiveRecord
181
203
  save_method = :"autosave_associated_records_for_#{reflection.name}"
182
204
 
183
205
  if reflection.collection?
184
- before_save :before_save_collection_association
185
- after_save :after_save_collection_association
206
+ around_save :around_save_collection_association
186
207
 
187
208
  define_non_cyclic_method(save_method) { save_collection_association(reflection) }
188
209
  # Doesn't use after_save as that would save associations added in after_create/after_update twice
@@ -267,7 +288,6 @@ module ActiveRecord
267
288
  end
268
289
 
269
290
  private
270
-
271
291
  # Returns the record for an association collection that should be validated
272
292
  # or saved. If +autosave+ is +false+ only new records will be returned,
273
293
  # unless the parent is/was a new record itself.
@@ -281,8 +301,9 @@ module ActiveRecord
281
301
  end
282
302
  end
283
303
 
284
- # go through nested autosave associations that are loaded in memory (without loading
285
- # any new ones), and return true if is changed for autosave
304
+ # Go through nested autosave associations that are loaded in memory (without loading
305
+ # any new ones), and return true if any are changed for autosave.
306
+ # Returns false if already called to prevent an infinite loop.
286
307
  def nested_records_changed_for_autosave?
287
308
  @_nested_records_changed_for_autosave_already_called ||= false
288
309
  return false if @_nested_records_changed_for_autosave_already_called
@@ -330,21 +351,16 @@ module ActiveRecord
330
351
  if reflection.options[:autosave]
331
352
  indexed_attribute = !index.nil? && (reflection.options[:index_errors] || ActiveRecord::Base.index_nested_attribute_errors)
332
353
 
333
- record.errors.each do |attribute, message|
354
+ record.errors.group_by_attribute.each { |attribute, errors|
334
355
  attribute = normalize_reflection_attribute(indexed_attribute, reflection, index, attribute)
335
- errors[attribute] << message
336
- errors[attribute].uniq!
337
- end
338
356
 
339
- record.errors.details.each_key do |attribute|
340
- reflection_attribute =
341
- normalize_reflection_attribute(indexed_attribute, reflection, index, attribute).to_sym
342
-
343
- record.errors.details[attribute].each do |error|
344
- errors.details[reflection_attribute] << error
345
- errors.details[reflection_attribute].uniq!
346
- end
347
- end
357
+ errors.each { |error|
358
+ self.errors.import(
359
+ error,
360
+ attribute: attribute
361
+ )
362
+ }
363
+ }
348
364
  else
349
365
  errors.add(reflection.name)
350
366
  end
@@ -360,14 +376,15 @@ module ActiveRecord
360
376
  end
361
377
  end
362
378
 
363
- # Is used as a before_save callback to check while saving a collection
379
+ # Is used as an around_save callback to check while saving a collection
364
380
  # association whether or not the parent was a new record before saving.
365
- def before_save_collection_association
366
- @new_record_before_save = new_record?
367
- end
381
+ def around_save_collection_association
382
+ previously_new_record_before_save = (@new_record_before_save ||= false)
383
+ @new_record_before_save = !previously_new_record_before_save && new_record?
368
384
 
369
- def after_save_collection_association
370
- @new_record_before_save = false
385
+ yield
386
+ ensure
387
+ @new_record_before_save = previously_new_record_before_save
371
388
  end
372
389
 
373
390
  # Saves any new associated records, or all loaded autosave associations if
@@ -416,7 +433,7 @@ module ActiveRecord
416
433
  saved = record.save(validate: false)
417
434
  end
418
435
 
419
- raise ActiveRecord::Rollback unless saved
436
+ raise(RecordInvalid.new(association.owner)) unless saved
420
437
  end
421
438
  end
422
439
  end
@@ -440,13 +457,13 @@ module ActiveRecord
440
457
  if autosave && record.marked_for_destruction?
441
458
  record.destroy
442
459
  elsif autosave != false
443
- key = reflection.options[:primary_key] ? send(reflection.options[:primary_key]) : id
460
+ key = reflection.options[:primary_key] ? public_send(reflection.options[:primary_key]) : id
444
461
 
445
- if (autosave && record.changed_for_autosave?) || new_record? || record_changed?(reflection, record, key)
462
+ if (autosave && record.changed_for_autosave?) || record_changed?(reflection, record, key)
446
463
  unless reflection.through_reflection
447
464
  record[reflection.foreign_key] = key
448
465
  if inverse_reflection = reflection.inverse_of
449
- record.association(inverse_reflection.name).loaded!
466
+ record.association(inverse_reflection.name).inversed_from(self)
450
467
  end
451
468
  end
452
469
 
@@ -468,7 +485,7 @@ module ActiveRecord
468
485
  def association_foreign_key_changed?(reflection, record, key)
469
486
  return false if reflection.through_reflection?
470
487
 
471
- record.has_attribute?(reflection.foreign_key) && record[reflection.foreign_key] != key
488
+ record._has_attribute?(reflection.foreign_key) && record._read_attribute(reflection.foreign_key) != key
472
489
  end
473
490
 
474
491
  # Saves the associated record if it's new or <tt>:autosave</tt> is enabled.
@@ -489,7 +506,7 @@ module ActiveRecord
489
506
  saved = record.save(validate: !autosave) if record.new_record? || (autosave && record.changed_for_autosave?)
490
507
 
491
508
  if association.updated?
492
- association_id = record.send(reflection.options[:primary_key] || :id)
509
+ association_id = record.public_send(reflection.options[:primary_key] || :id)
493
510
  self[reflection.foreign_key] = association_id
494
511
  association.loaded!
495
512
  end
@@ -504,9 +521,7 @@ module ActiveRecord
504
521
  end
505
522
 
506
523
  def _ensure_no_duplicate_errors
507
- errors.messages.each_key do |attribute|
508
- errors[attribute].uniq!
509
- end
524
+ errors.uniq!
510
525
  end
511
526
  end
512
527
  end
@@ -1,28 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "yaml"
4
3
  require "active_support/benchmarkable"
5
4
  require "active_support/dependencies"
6
5
  require "active_support/descendants_tracker"
7
6
  require "active_support/time"
8
- require "active_support/core_ext/module/attribute_accessors"
9
- require "active_support/core_ext/array/extract_options"
10
- require "active_support/core_ext/hash/deep_merge"
11
- require "active_support/core_ext/hash/slice"
12
- require "active_support/core_ext/hash/transform_values"
13
- require "active_support/core_ext/string/behavior"
14
- require "active_support/core_ext/kernel/singleton_class"
15
- require "active_support/core_ext/module/introspection"
16
- require "active_support/core_ext/object/duplicable"
17
7
  require "active_support/core_ext/class/subclasses"
18
- require "active_record/attribute_decorators"
19
- require "active_record/define_callbacks"
20
- require "active_record/errors"
21
8
  require "active_record/log_subscriber"
22
9
  require "active_record/explain_subscriber"
23
10
  require "active_record/relation/delegation"
24
11
  require "active_record/attributes"
25
12
  require "active_record/type_caster"
13
+ require "active_record/database_configurations"
26
14
 
27
15
  module ActiveRecord #:nodoc:
28
16
  # = Active Record
@@ -285,10 +273,11 @@ module ActiveRecord #:nodoc:
285
273
  extend Querying
286
274
  extend Translation
287
275
  extend DynamicMatchers
276
+ extend DelegatedType
288
277
  extend Explain
289
278
  extend Enum
290
279
  extend Delegation::DelegateCache
291
- extend CollectionCacheKey
280
+ extend Aggregations::ClassMethods
292
281
 
293
282
  include Core
294
283
  include Persistence
@@ -303,10 +292,8 @@ module ActiveRecord #:nodoc:
303
292
  include Validations
304
293
  include CounterCache
305
294
  include Attributes
306
- include AttributeDecorators
307
295
  include Locking::Optimistic
308
296
  include Locking::Pessimistic
309
- include DefineCallbacks
310
297
  include AttributeMethods
311
298
  include Callbacks
312
299
  include Timestamp
@@ -314,7 +301,6 @@ module ActiveRecord #:nodoc:
314
301
  include ActiveModel::SecurePassword
315
302
  include AutosaveAssociation
316
303
  include NestedAttributes
317
- include Aggregations
318
304
  include Transactions
319
305
  include TouchLater
320
306
  include NoTouching
@@ -322,6 +308,7 @@ module ActiveRecord #:nodoc:
322
308
  include Serialization
323
309
  include Store
324
310
  include SecureToken
311
+ include SignedId
325
312
  include Suppressor
326
313
  end
327
314
 
@@ -4,7 +4,7 @@ module ActiveRecord
4
4
  # = Active Record \Callbacks
5
5
  #
6
6
  # \Callbacks are hooks into the life cycle of an Active Record object that allow you to trigger logic
7
- # before or after an alteration of the object state. This can be used to make sure that associated and
7
+ # before or after a change in the object state. This can be used to make sure that associated and
8
8
  # dependent objects are deleted when {ActiveRecord::Base#destroy}[rdoc-ref:Persistence#destroy] is called (by overwriting +before_destroy+) or
9
9
  # to massage attributes before they're validated (by overwriting +before_validation+).
10
10
  # As an example of the callbacks initiated, consider the {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] call for a new record:
@@ -32,7 +32,7 @@ module ActiveRecord
32
32
  # is found and instantiated by a finder, with <tt>after_initialize</tt> being triggered after new objects
33
33
  # are instantiated as well.
34
34
  #
35
- # There are nineteen callbacks in total, which give you immense power to react and prepare for each state in the
35
+ # There are nineteen callbacks in total, which give a lot of control over how to react and prepare for each state in the
36
36
  # Active Record life cycle. The sequence for calling {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] for an existing record is similar,
37
37
  # except that each <tt>_create</tt> callback is replaced by the corresponding <tt>_update</tt> callback.
38
38
  #
@@ -64,7 +64,7 @@ module ActiveRecord
64
64
  #
65
65
  # Besides the overwritable callback methods, it's also possible to register callbacks through the
66
66
  # use of the callback macros. Their main advantage is that the macros add behavior into a callback
67
- # queue that is kept intact down through an inheritance hierarchy.
67
+ # queue that is kept intact through an inheritance hierarchy.
68
68
  #
69
69
  # class Topic < ActiveRecord::Base
70
70
  # before_destroy :destroy_author
@@ -74,22 +74,8 @@ module ActiveRecord
74
74
  # before_destroy :destroy_readers
75
75
  # end
76
76
  #
77
- # Now, when <tt>Topic#destroy</tt> is run only +destroy_author+ is called. When <tt>Reply#destroy</tt> is
78
- # run, both +destroy_author+ and +destroy_readers+ are called. Contrast this to the following situation
79
- # where the +before_destroy+ method is overridden:
80
- #
81
- # class Topic < ActiveRecord::Base
82
- # def before_destroy() destroy_author end
83
- # end
84
- #
85
- # class Reply < Topic
86
- # def before_destroy() destroy_readers end
87
- # end
88
- #
89
- # In that case, <tt>Reply#destroy</tt> would only run +destroy_readers+ and _not_ +destroy_author+.
90
- # So, use the callback macros when you want to ensure that a certain callback is called for the entire
91
- # hierarchy, and use the regular overwritable methods when you want to leave it up to each descendant
92
- # to decide whether they want to call +super+ and trigger the inherited callbacks.
77
+ # When <tt>Topic#destroy</tt> is run only +destroy_author+ is called. When <tt>Reply#destroy</tt> is
78
+ # run, both +destroy_author+ and +destroy_readers+ are called.
93
79
  #
94
80
  # *IMPORTANT:* In order for inheritance to work for the callback queues, you must specify the
95
81
  # callbacks before specifying the associations. Otherwise, you might trigger the loading of a
@@ -97,10 +83,9 @@ module ActiveRecord
97
83
  #
98
84
  # == Types of callbacks
99
85
  #
100
- # There are four types of callbacks accepted by the callback macros: Method references (symbol), callback objects,
101
- # inline methods (using a proc). Method references and callback objects
102
- # are the recommended approaches, inline methods using a proc are sometimes appropriate (such as for
103
- # creating mix-ins).
86
+ # There are three types of callbacks accepted by the callback macros: method references (symbol), callback objects,
87
+ # inline methods (using a proc). Method references and callback objects are the recommended approaches,
88
+ # inline methods using a proc are sometimes appropriate (such as for creating mix-ins).
104
89
  #
105
90
  # The method reference callbacks work by specifying a protected or private method available in the object, like this:
106
91
  #
@@ -109,7 +94,7 @@ module ActiveRecord
109
94
  #
110
95
  # private
111
96
  # def delete_parents
112
- # self.class.delete_all "parent_id = #{id}"
97
+ # self.class.delete_by(parent_id: id)
113
98
  # end
114
99
  # end
115
100
  #
@@ -142,7 +127,7 @@ module ActiveRecord
142
127
  # end
143
128
  # end
144
129
  #
145
- # So you specify the object you want messaged on a given callback. When that callback is triggered, the object has
130
+ # So you specify the object you want to be messaged on a given callback. When that callback is triggered, the object has
146
131
  # a method by the name of the callback messaged. You can make these callbacks more flexible by passing in other
147
132
  # initialization data such as the name of the attribute to work with:
148
133
  #
@@ -193,8 +178,8 @@ module ActiveRecord
193
178
  #
194
179
  # == Ordering callbacks
195
180
  #
196
- # Sometimes the code needs that the callbacks execute in a specific order. For example, a +before_destroy+
197
- # callback (+log_children+ in this case) should be executed before the children get destroyed by the
181
+ # Sometimes application code requires that callbacks execute in a specific order. For example, a +before_destroy+
182
+ # callback (+log_children+ in this case) should be executed before records in the +children+ association are destroyed by the
198
183
  # <tt>dependent: :destroy</tt> option.
199
184
  #
200
185
  # Let's look at the code below:
@@ -210,8 +195,8 @@ module ActiveRecord
210
195
  # end
211
196
  # end
212
197
  #
213
- # In this case, the problem is that when the +before_destroy+ callback is executed, the children are not available
214
- # because the {ActiveRecord::Base#destroy}[rdoc-ref:Persistence#destroy] callback gets executed first.
198
+ # In this case, the problem is that when the +before_destroy+ callback is executed, records in the +children+ association no
199
+ # longer exist because the {ActiveRecord::Base#destroy}[rdoc-ref:Persistence#destroy] callback was executed first.
215
200
  # You can use the +prepend+ option on the +before_destroy+ callback to avoid this.
216
201
  #
217
202
  # class Topic < ActiveRecord::Base
@@ -225,7 +210,7 @@ module ActiveRecord
225
210
  # end
226
211
  # end
227
212
  #
228
- # This way, the +before_destroy+ gets executed before the <tt>dependent: :destroy</tt> is called, and the data is still available.
213
+ # This way, the +before_destroy+ is executed before the <tt>dependent: :destroy</tt> is called, and the data is still available.
229
214
  #
230
215
  # Also, there are cases when you want several callbacks of the same type to
231
216
  # be executed in order.
@@ -249,10 +234,10 @@ module ActiveRecord
249
234
  # end
250
235
  # end
251
236
  #
252
- # In this case the +log_children+ gets executed before +do_something_else+.
237
+ # In this case the +log_children+ is executed before +do_something_else+.
253
238
  # The same applies to all non-transactional callbacks.
254
239
  #
255
- # In case there are multiple transactional callbacks as seen below, the order
240
+ # As seen below, in case there are multiple transactional callbacks the order
256
241
  # is reversed.
257
242
  #
258
243
  # For example:
@@ -274,16 +259,16 @@ module ActiveRecord
274
259
  # end
275
260
  # end
276
261
  #
277
- # In this case the +do_something_else+ gets executed before +log_children+.
262
+ # In this case the +do_something_else+ is executed before +log_children+.
278
263
  #
279
264
  # == \Transactions
280
265
  #
281
266
  # The entire callback chain of a {#save}[rdoc-ref:Persistence#save], {#save!}[rdoc-ref:Persistence#save!],
282
267
  # or {#destroy}[rdoc-ref:Persistence#destroy] call runs within a transaction. That includes <tt>after_*</tt> hooks.
283
- # If everything goes fine a COMMIT is executed once the chain has been completed.
268
+ # If everything goes fine a +COMMIT+ is executed once the chain has been completed.
284
269
  #
285
- # If a <tt>before_*</tt> callback cancels the action a ROLLBACK is issued. You
286
- # can also trigger a ROLLBACK raising an exception in any of the callbacks,
270
+ # If a <tt>before_*</tt> callback cancels the action a +ROLLBACK+ is issued. You
271
+ # can also trigger a +ROLLBACK+ raising an exception in any of the callbacks,
287
272
  # including <tt>after_*</tt> hooks. Note, however, that in that case the client
288
273
  # needs to be aware of it because an ordinary {#save}[rdoc-ref:Persistence#save] will raise such exception
289
274
  # instead of quietly returning +false+.
@@ -294,17 +279,17 @@ module ActiveRecord
294
279
  # <tt>:before</tt>, <tt>:after</tt> and <tt>:around</tt> as values for the <tt>kind</tt> property. The <tt>kind</tt> property
295
280
  # defines what part of the chain the callback runs in.
296
281
  #
297
- # To find all callbacks in the before_save callback chain:
282
+ # To find all callbacks in the +before_save+ callback chain:
298
283
  #
299
284
  # Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }
300
285
  #
301
- # Returns an array of callback objects that form the before_save chain.
286
+ # Returns an array of callback objects that form the +before_save+ chain.
302
287
  #
303
288
  # To further check if the before_save chain contains a proc defined as <tt>rest_when_dead</tt> use the <tt>filter</tt> property of the callback object:
304
289
  #
305
290
  # Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }.collect(&:filter).include?(:rest_when_dead)
306
291
  #
307
- # Returns true or false depending on whether the proc is contained in the before_save callback chain on a Topic model.
292
+ # Returns true or false depending on whether the proc is contained in the +before_save+ callback chain on a Topic model.
308
293
  #
309
294
  module Callbacks
310
295
  extend ActiveSupport::Concern
@@ -316,6 +301,137 @@ module ActiveRecord
316
301
  :before_destroy, :around_destroy, :after_destroy, :after_commit, :after_rollback
317
302
  ]
318
303
 
304
+ module ClassMethods
305
+ include ActiveModel::Callbacks
306
+
307
+ ##
308
+ # :method: after_initialize
309
+ #
310
+ # :call-seq: after_initialize(*args, &block)
311
+ #
312
+ # Registers a callback to be called after a record is instantiated. See
313
+ # ActiveRecord::Callbacks for more information.
314
+
315
+ ##
316
+ # :method: after_find
317
+ #
318
+ # :call-seq: after_find(*args, &block)
319
+ #
320
+ # Registers a callback to be called after a record is instantiated
321
+ # via a finder. See ActiveRecord::Callbacks for more information.
322
+
323
+ ##
324
+ # :method: after_touch
325
+ #
326
+ # :call-seq: after_touch(*args, &block)
327
+ #
328
+ # Registers a callback to be called after a record is touched. See
329
+ # ActiveRecord::Callbacks for more information.
330
+
331
+ ##
332
+ # :method: before_save
333
+ #
334
+ # :call-seq: before_save(*args, &block)
335
+ #
336
+ # Registers a callback to be called before a record is saved. See
337
+ # ActiveRecord::Callbacks for more information.
338
+
339
+ ##
340
+ # :method: around_save
341
+ #
342
+ # :call-seq: around_save(*args, &block)
343
+ #
344
+ # Registers a callback to be called around the save of a record. See
345
+ # ActiveRecord::Callbacks for more information.
346
+
347
+ ##
348
+ # :method: after_save
349
+ #
350
+ # :call-seq: after_save(*args, &block)
351
+ #
352
+ # Registers a callback to be called after a record is saved. See
353
+ # ActiveRecord::Callbacks for more information.
354
+
355
+ ##
356
+ # :method: before_create
357
+ #
358
+ # :call-seq: before_create(*args, &block)
359
+ #
360
+ # Registers a callback to be called before a record is created. See
361
+ # ActiveRecord::Callbacks for more information.
362
+
363
+ ##
364
+ # :method: around_create
365
+ #
366
+ # :call-seq: around_create(*args, &block)
367
+ #
368
+ # Registers a callback to be called around the creation of a record. See
369
+ # ActiveRecord::Callbacks for more information.
370
+
371
+ ##
372
+ # :method: after_create
373
+ #
374
+ # :call-seq: after_create(*args, &block)
375
+ #
376
+ # Registers a callback to be called after a record is created. See
377
+ # ActiveRecord::Callbacks for more information.
378
+
379
+ ##
380
+ # :method: before_update
381
+ #
382
+ # :call-seq: before_update(*args, &block)
383
+ #
384
+ # Registers a callback to be called before a record is updated. See
385
+ # ActiveRecord::Callbacks for more information.
386
+
387
+ ##
388
+ # :method: around_update
389
+ #
390
+ # :call-seq: around_update(*args, &block)
391
+ #
392
+ # Registers a callback to be called around the update of a record. See
393
+ # ActiveRecord::Callbacks for more information.
394
+
395
+ ##
396
+ # :method: after_update
397
+ #
398
+ # :call-seq: after_update(*args, &block)
399
+ #
400
+ # Registers a callback to be called after a record is updated. See
401
+ # ActiveRecord::Callbacks for more information.
402
+
403
+ ##
404
+ # :method: before_destroy
405
+ #
406
+ # :call-seq: before_destroy(*args, &block)
407
+ #
408
+ # Registers a callback to be called before a record is destroyed. See
409
+ # ActiveRecord::Callbacks for more information.
410
+
411
+ ##
412
+ # :method: around_destroy
413
+ #
414
+ # :call-seq: around_destroy(*args, &block)
415
+ #
416
+ # Registers a callback to be called around the destruction of a record.
417
+ # See ActiveRecord::Callbacks for more information.
418
+
419
+ ##
420
+ # :method: after_destroy
421
+ #
422
+ # :call-seq: after_destroy(*args, &block)
423
+ #
424
+ # Registers a callback to be called after a record is destroyed. See
425
+ # ActiveRecord::Callbacks for more information.
426
+ end
427
+
428
+ included do
429
+ include ActiveModel::Validations::Callbacks
430
+
431
+ define_model_callbacks :initialize, :find, :touch, only: :after
432
+ define_model_callbacks :save, :create, :update, :destroy
433
+ end
434
+
319
435
  def destroy #:nodoc:
320
436
  @_destroy_callback_already_called ||= false
321
437
  return if @_destroy_callback_already_called
@@ -328,7 +444,7 @@ module ActiveRecord
328
444
  @_destroy_callback_already_called = false
329
445
  end
330
446
 
331
- def touch(*) #:nodoc:
447
+ def touch(*, **) #:nodoc:
332
448
  _run_touch_callbacks { super }
333
449
  end
334
450
 
@@ -337,8 +453,7 @@ module ActiveRecord
337
453
  end
338
454
 
339
455
  private
340
-
341
- def create_or_update(*)
456
+ def create_or_update(**)
342
457
  _run_save_callbacks { super }
343
458
  end
344
459
 
@@ -346,7 +461,7 @@ module ActiveRecord
346
461
  _run_create_callbacks { super }
347
462
  end
348
463
 
349
- def _update_record(*)
464
+ def _update_record
350
465
  _run_update_callbacks { super }
351
466
  end
352
467
  end
@@ -22,7 +22,7 @@ module ActiveRecord
22
22
 
23
23
  def load(yaml)
24
24
  return object_class.new if object_class != Object && yaml.nil?
25
- return yaml unless yaml.is_a?(String) && /^---/.match?(yaml)
25
+ return yaml unless yaml.is_a?(String) && yaml.start_with?("---")
26
26
  obj = yaml_load(yaml)
27
27
 
28
28
  assert_valid_value(obj, action: "load")
@@ -39,21 +39,30 @@ module ActiveRecord
39
39
  end
40
40
 
41
41
  private
42
-
43
42
  def check_arity_of_constructor
44
43
  load(nil)
45
44
  rescue ArgumentError
46
45
  raise ArgumentError, "Cannot serialize #{object_class}. Classes passed to `serialize` must have a 0 argument constructor."
47
46
  end
48
47
 
49
- def yaml_load(payload)
50
- if !ActiveRecord::Base.use_yaml_unsafe_load
51
- YAML.safe_load(payload, permitted_classes: ActiveRecord::Base.yaml_column_permitted_classes, aliases: true)
52
- else
53
- if YAML.respond_to?(:unsafe_load)
48
+ if YAML.respond_to?(:unsafe_load)
49
+ def yaml_load(payload)
50
+ if ActiveRecord::Base.use_yaml_unsafe_load
54
51
  YAML.unsafe_load(payload)
52
+ elsif YAML.method(:safe_load).parameters.include?([:key, :permitted_classes])
53
+ YAML.safe_load(payload, permitted_classes: ActiveRecord::Base.yaml_column_permitted_classes, aliases: true)
55
54
  else
55
+ YAML.safe_load(payload, ActiveRecord::Base.yaml_column_permitted_classes, [], true)
56
+ end
57
+ end
58
+ else
59
+ def yaml_load(payload)
60
+ if ActiveRecord::Base.use_yaml_unsafe_load
56
61
  YAML.load(payload)
62
+ elsif YAML.method(:safe_load).parameters.include?([:key, :permitted_classes])
63
+ YAML.safe_load(payload, permitted_classes: ActiveRecord::Base.yaml_column_permitted_classes, aliases: true)
64
+ else
65
+ YAML.safe_load(payload, ActiveRecord::Base.yaml_column_permitted_classes, [], true)
57
66
  end
58
67
  end
59
68
  end