activerecord 6.0.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 (340) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1086 -0
  3. data/MIT-LICENSE +22 -0
  4. data/README.rdoc +219 -0
  5. data/examples/performance.rb +185 -0
  6. data/examples/simple.rb +15 -0
  7. data/lib/active_record.rb +195 -0
  8. data/lib/active_record/aggregations.rb +285 -0
  9. data/lib/active_record/association_relation.rb +49 -0
  10. data/lib/active_record/associations.rb +1865 -0
  11. data/lib/active_record/associations/alias_tracker.rb +81 -0
  12. data/lib/active_record/associations/association.rb +340 -0
  13. data/lib/active_record/associations/association_scope.rb +166 -0
  14. data/lib/active_record/associations/belongs_to_association.rb +124 -0
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +36 -0
  16. data/lib/active_record/associations/builder/association.rb +136 -0
  17. data/lib/active_record/associations/builder/belongs_to.rb +130 -0
  18. data/lib/active_record/associations/builder/collection_association.rb +72 -0
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +114 -0
  20. data/lib/active_record/associations/builder/has_many.rb +19 -0
  21. data/lib/active_record/associations/builder/has_one.rb +64 -0
  22. data/lib/active_record/associations/builder/singular_association.rb +44 -0
  23. data/lib/active_record/associations/collection_association.rb +498 -0
  24. data/lib/active_record/associations/collection_proxy.rb +1128 -0
  25. data/lib/active_record/associations/foreign_association.rb +20 -0
  26. data/lib/active_record/associations/has_many_association.rb +136 -0
  27. data/lib/active_record/associations/has_many_through_association.rb +220 -0
  28. data/lib/active_record/associations/has_one_association.rb +118 -0
  29. data/lib/active_record/associations/has_one_through_association.rb +45 -0
  30. data/lib/active_record/associations/join_dependency.rb +262 -0
  31. data/lib/active_record/associations/join_dependency/join_association.rb +80 -0
  32. data/lib/active_record/associations/join_dependency/join_base.rb +23 -0
  33. data/lib/active_record/associations/join_dependency/join_part.rb +71 -0
  34. data/lib/active_record/associations/preloader.rb +201 -0
  35. data/lib/active_record/associations/preloader/association.rb +133 -0
  36. data/lib/active_record/associations/preloader/through_association.rb +116 -0
  37. data/lib/active_record/associations/singular_association.rb +59 -0
  38. data/lib/active_record/associations/through_association.rb +121 -0
  39. data/lib/active_record/attribute_assignment.rb +85 -0
  40. data/lib/active_record/attribute_decorators.rb +90 -0
  41. data/lib/active_record/attribute_methods.rb +420 -0
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +81 -0
  43. data/lib/active_record/attribute_methods/dirty.rb +221 -0
  44. data/lib/active_record/attribute_methods/primary_key.rb +136 -0
  45. data/lib/active_record/attribute_methods/query.rb +41 -0
  46. data/lib/active_record/attribute_methods/read.rb +47 -0
  47. data/lib/active_record/attribute_methods/serialization.rb +90 -0
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +91 -0
  49. data/lib/active_record/attribute_methods/write.rb +61 -0
  50. data/lib/active_record/attributes.rb +279 -0
  51. data/lib/active_record/autosave_association.rb +512 -0
  52. data/lib/active_record/base.rb +328 -0
  53. data/lib/active_record/callbacks.rb +339 -0
  54. data/lib/active_record/coders/json.rb +15 -0
  55. data/lib/active_record/coders/yaml_column.rb +50 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +1175 -0
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +85 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +516 -0
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +155 -0
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +251 -0
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +713 -0
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +93 -0
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1475 -0
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +323 -0
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +772 -0
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +830 -0
  69. data/lib/active_record/connection_adapters/column.rb +95 -0
  70. data/lib/active_record/connection_adapters/connection_specification.rb +297 -0
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +202 -0
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +146 -0
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +30 -0
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +184 -0
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +92 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +53 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +23 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +41 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +113 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +26 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +205 -0
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +43 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +222 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +776 -0
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +953 -0
  117. data/lib/active_record/connection_adapters/schema_cache.rb +141 -0
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
  119. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +120 -0
  120. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  121. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +103 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  126. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +561 -0
  127. data/lib/active_record/connection_adapters/statement_pool.rb +61 -0
  128. data/lib/active_record/connection_handling.rb +274 -0
  129. data/lib/active_record/core.rb +603 -0
  130. data/lib/active_record/counter_cache.rb +193 -0
  131. data/lib/active_record/database_configurations.rb +233 -0
  132. data/lib/active_record/database_configurations/database_config.rb +37 -0
  133. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  134. data/lib/active_record/database_configurations/url_config.rb +79 -0
  135. data/lib/active_record/define_callbacks.rb +22 -0
  136. data/lib/active_record/dynamic_matchers.rb +122 -0
  137. data/lib/active_record/enum.rb +274 -0
  138. data/lib/active_record/errors.rb +388 -0
  139. data/lib/active_record/explain.rb +50 -0
  140. data/lib/active_record/explain_registry.rb +32 -0
  141. data/lib/active_record/explain_subscriber.rb +34 -0
  142. data/lib/active_record/fixture_set/file.rb +82 -0
  143. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  144. data/lib/active_record/fixture_set/render_context.rb +17 -0
  145. data/lib/active_record/fixture_set/table_row.rb +153 -0
  146. data/lib/active_record/fixture_set/table_rows.rb +47 -0
  147. data/lib/active_record/fixtures.rb +738 -0
  148. data/lib/active_record/gem_version.rb +17 -0
  149. data/lib/active_record/inheritance.rb +293 -0
  150. data/lib/active_record/insert_all.rb +179 -0
  151. data/lib/active_record/integration.rb +207 -0
  152. data/lib/active_record/internal_metadata.rb +53 -0
  153. data/lib/active_record/legacy_yaml_adapter.rb +48 -0
  154. data/lib/active_record/locale/en.yml +48 -0
  155. data/lib/active_record/locking/optimistic.rb +197 -0
  156. data/lib/active_record/locking/pessimistic.rb +89 -0
  157. data/lib/active_record/log_subscriber.rb +118 -0
  158. data/lib/active_record/middleware/database_selector.rb +75 -0
  159. data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
  160. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  161. data/lib/active_record/migration.rb +1397 -0
  162. data/lib/active_record/migration/command_recorder.rb +284 -0
  163. data/lib/active_record/migration/compatibility.rb +244 -0
  164. data/lib/active_record/migration/join_table.rb +17 -0
  165. data/lib/active_record/model_schema.rb +545 -0
  166. data/lib/active_record/nested_attributes.rb +600 -0
  167. data/lib/active_record/no_touching.rb +65 -0
  168. data/lib/active_record/null_relation.rb +68 -0
  169. data/lib/active_record/persistence.rb +967 -0
  170. data/lib/active_record/query_cache.rb +52 -0
  171. data/lib/active_record/querying.rb +82 -0
  172. data/lib/active_record/railtie.rb +263 -0
  173. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  174. data/lib/active_record/railties/console_sandbox.rb +7 -0
  175. data/lib/active_record/railties/controller_runtime.rb +51 -0
  176. data/lib/active_record/railties/databases.rake +527 -0
  177. data/lib/active_record/readonly_attributes.rb +24 -0
  178. data/lib/active_record/reflection.rb +1042 -0
  179. data/lib/active_record/relation.rb +860 -0
  180. data/lib/active_record/relation/batches.rb +290 -0
  181. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  182. data/lib/active_record/relation/calculations.rb +424 -0
  183. data/lib/active_record/relation/delegation.rb +130 -0
  184. data/lib/active_record/relation/finder_methods.rb +561 -0
  185. data/lib/active_record/relation/from_clause.rb +26 -0
  186. data/lib/active_record/relation/merger.rb +184 -0
  187. data/lib/active_record/relation/predicate_builder.rb +150 -0
  188. data/lib/active_record/relation/predicate_builder/array_handler.rb +49 -0
  189. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  190. data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
  191. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  192. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  193. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  194. data/lib/active_record/relation/predicate_builder/relation_handler.rb +19 -0
  195. data/lib/active_record/relation/query_attribute.rb +50 -0
  196. data/lib/active_record/relation/query_methods.rb +1371 -0
  197. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  198. data/lib/active_record/relation/spawn_methods.rb +77 -0
  199. data/lib/active_record/relation/where_clause.rb +190 -0
  200. data/lib/active_record/relation/where_clause_factory.rb +33 -0
  201. data/lib/active_record/result.rb +168 -0
  202. data/lib/active_record/runtime_registry.rb +24 -0
  203. data/lib/active_record/sanitization.rb +214 -0
  204. data/lib/active_record/schema.rb +61 -0
  205. data/lib/active_record/schema_dumper.rb +270 -0
  206. data/lib/active_record/schema_migration.rb +60 -0
  207. data/lib/active_record/scoping.rb +106 -0
  208. data/lib/active_record/scoping/default.rb +151 -0
  209. data/lib/active_record/scoping/named.rb +217 -0
  210. data/lib/active_record/secure_token.rb +40 -0
  211. data/lib/active_record/serialization.rb +22 -0
  212. data/lib/active_record/statement_cache.rb +148 -0
  213. data/lib/active_record/store.rb +290 -0
  214. data/lib/active_record/suppressor.rb +61 -0
  215. data/lib/active_record/table_metadata.rb +75 -0
  216. data/lib/active_record/tasks/database_tasks.rb +506 -0
  217. data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
  218. data/lib/active_record/tasks/postgresql_database_tasks.rb +141 -0
  219. data/lib/active_record/tasks/sqlite_database_tasks.rb +77 -0
  220. data/lib/active_record/test_databases.rb +23 -0
  221. data/lib/active_record/test_fixtures.rb +224 -0
  222. data/lib/active_record/timestamp.rb +167 -0
  223. data/lib/active_record/touch_later.rb +66 -0
  224. data/lib/active_record/transactions.rb +493 -0
  225. data/lib/active_record/translation.rb +24 -0
  226. data/lib/active_record/type.rb +78 -0
  227. data/lib/active_record/type/adapter_specific_registry.rb +129 -0
  228. data/lib/active_record/type/date.rb +9 -0
  229. data/lib/active_record/type/date_time.rb +9 -0
  230. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  231. data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
  232. data/lib/active_record/type/internal/timezone.rb +17 -0
  233. data/lib/active_record/type/json.rb +30 -0
  234. data/lib/active_record/type/serialized.rb +71 -0
  235. data/lib/active_record/type/text.rb +11 -0
  236. data/lib/active_record/type/time.rb +21 -0
  237. data/lib/active_record/type/type_map.rb +62 -0
  238. data/lib/active_record/type/unsigned_integer.rb +17 -0
  239. data/lib/active_record/type_caster.rb +9 -0
  240. data/lib/active_record/type_caster/connection.rb +34 -0
  241. data/lib/active_record/type_caster/map.rb +20 -0
  242. data/lib/active_record/validations.rb +94 -0
  243. data/lib/active_record/validations/absence.rb +25 -0
  244. data/lib/active_record/validations/associated.rb +60 -0
  245. data/lib/active_record/validations/length.rb +26 -0
  246. data/lib/active_record/validations/presence.rb +68 -0
  247. data/lib/active_record/validations/uniqueness.rb +226 -0
  248. data/lib/active_record/version.rb +10 -0
  249. data/lib/arel.rb +58 -0
  250. data/lib/arel/alias_predication.rb +9 -0
  251. data/lib/arel/attributes.rb +22 -0
  252. data/lib/arel/attributes/attribute.rb +37 -0
  253. data/lib/arel/collectors/bind.rb +24 -0
  254. data/lib/arel/collectors/composite.rb +31 -0
  255. data/lib/arel/collectors/plain_string.rb +20 -0
  256. data/lib/arel/collectors/sql_string.rb +20 -0
  257. data/lib/arel/collectors/substitute_binds.rb +28 -0
  258. data/lib/arel/crud.rb +42 -0
  259. data/lib/arel/delete_manager.rb +18 -0
  260. data/lib/arel/errors.rb +9 -0
  261. data/lib/arel/expressions.rb +29 -0
  262. data/lib/arel/factory_methods.rb +49 -0
  263. data/lib/arel/insert_manager.rb +49 -0
  264. data/lib/arel/math.rb +45 -0
  265. data/lib/arel/nodes.rb +68 -0
  266. data/lib/arel/nodes/and.rb +32 -0
  267. data/lib/arel/nodes/ascending.rb +23 -0
  268. data/lib/arel/nodes/binary.rb +52 -0
  269. data/lib/arel/nodes/bind_param.rb +36 -0
  270. data/lib/arel/nodes/case.rb +55 -0
  271. data/lib/arel/nodes/casted.rb +50 -0
  272. data/lib/arel/nodes/comment.rb +29 -0
  273. data/lib/arel/nodes/count.rb +12 -0
  274. data/lib/arel/nodes/delete_statement.rb +45 -0
  275. data/lib/arel/nodes/descending.rb +23 -0
  276. data/lib/arel/nodes/equality.rb +18 -0
  277. data/lib/arel/nodes/extract.rb +24 -0
  278. data/lib/arel/nodes/false.rb +16 -0
  279. data/lib/arel/nodes/full_outer_join.rb +8 -0
  280. data/lib/arel/nodes/function.rb +44 -0
  281. data/lib/arel/nodes/grouping.rb +8 -0
  282. data/lib/arel/nodes/in.rb +8 -0
  283. data/lib/arel/nodes/infix_operation.rb +80 -0
  284. data/lib/arel/nodes/inner_join.rb +8 -0
  285. data/lib/arel/nodes/insert_statement.rb +37 -0
  286. data/lib/arel/nodes/join_source.rb +20 -0
  287. data/lib/arel/nodes/matches.rb +18 -0
  288. data/lib/arel/nodes/named_function.rb +23 -0
  289. data/lib/arel/nodes/node.rb +50 -0
  290. data/lib/arel/nodes/node_expression.rb +13 -0
  291. data/lib/arel/nodes/outer_join.rb +8 -0
  292. data/lib/arel/nodes/over.rb +15 -0
  293. data/lib/arel/nodes/regexp.rb +16 -0
  294. data/lib/arel/nodes/right_outer_join.rb +8 -0
  295. data/lib/arel/nodes/select_core.rb +67 -0
  296. data/lib/arel/nodes/select_statement.rb +41 -0
  297. data/lib/arel/nodes/sql_literal.rb +16 -0
  298. data/lib/arel/nodes/string_join.rb +11 -0
  299. data/lib/arel/nodes/table_alias.rb +27 -0
  300. data/lib/arel/nodes/terminal.rb +16 -0
  301. data/lib/arel/nodes/true.rb +16 -0
  302. data/lib/arel/nodes/unary.rb +45 -0
  303. data/lib/arel/nodes/unary_operation.rb +20 -0
  304. data/lib/arel/nodes/unqualified_column.rb +22 -0
  305. data/lib/arel/nodes/update_statement.rb +41 -0
  306. data/lib/arel/nodes/values_list.rb +9 -0
  307. data/lib/arel/nodes/window.rb +126 -0
  308. data/lib/arel/nodes/with.rb +11 -0
  309. data/lib/arel/order_predications.rb +13 -0
  310. data/lib/arel/predications.rb +257 -0
  311. data/lib/arel/select_manager.rb +271 -0
  312. data/lib/arel/table.rb +110 -0
  313. data/lib/arel/tree_manager.rb +72 -0
  314. data/lib/arel/update_manager.rb +34 -0
  315. data/lib/arel/visitors.rb +20 -0
  316. data/lib/arel/visitors/depth_first.rb +204 -0
  317. data/lib/arel/visitors/dot.rb +297 -0
  318. data/lib/arel/visitors/ibm_db.rb +34 -0
  319. data/lib/arel/visitors/informix.rb +62 -0
  320. data/lib/arel/visitors/mssql.rb +157 -0
  321. data/lib/arel/visitors/mysql.rb +83 -0
  322. data/lib/arel/visitors/oracle.rb +159 -0
  323. data/lib/arel/visitors/oracle12.rb +66 -0
  324. data/lib/arel/visitors/postgresql.rb +110 -0
  325. data/lib/arel/visitors/sqlite.rb +39 -0
  326. data/lib/arel/visitors/to_sql.rb +889 -0
  327. data/lib/arel/visitors/visitor.rb +46 -0
  328. data/lib/arel/visitors/where_sql.rb +23 -0
  329. data/lib/arel/window_predications.rb +9 -0
  330. data/lib/rails/generators/active_record.rb +19 -0
  331. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  332. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  333. data/lib/rails/generators/active_record/migration.rb +48 -0
  334. data/lib/rails/generators/active_record/migration/migration_generator.rb +75 -0
  335. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  336. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +48 -0
  337. data/lib/rails/generators/active_record/model/model_generator.rb +49 -0
  338. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  339. data/lib/rails/generators/active_record/model/templates/module.rb.tt +7 -0
  340. metadata +418 -0
@@ -0,0 +1,328 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+ require "active_support/benchmarkable"
5
+ require "active_support/dependencies"
6
+ require "active_support/descendants_tracker"
7
+ 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/string/behavior"
13
+ require "active_support/core_ext/kernel/singleton_class"
14
+ require "active_support/core_ext/module/introspection"
15
+ require "active_support/core_ext/object/duplicable"
16
+ require "active_support/core_ext/class/subclasses"
17
+ require "active_record/attribute_decorators"
18
+ require "active_record/define_callbacks"
19
+ require "active_record/errors"
20
+ require "active_record/log_subscriber"
21
+ require "active_record/explain_subscriber"
22
+ require "active_record/relation/delegation"
23
+ require "active_record/attributes"
24
+ require "active_record/type_caster"
25
+ require "active_record/database_configurations"
26
+
27
+ module ActiveRecord #:nodoc:
28
+ # = Active Record
29
+ #
30
+ # Active Record objects don't specify their attributes directly, but rather infer them from
31
+ # the table definition with which they're linked. Adding, removing, and changing attributes
32
+ # and their type is done directly in the database. Any change is instantly reflected in the
33
+ # Active Record objects. The mapping that binds a given Active Record class to a certain
34
+ # database table will happen automatically in most common cases, but can be overwritten for the uncommon ones.
35
+ #
36
+ # See the mapping rules in table_name and the full example in link:files/activerecord/README_rdoc.html for more insight.
37
+ #
38
+ # == Creation
39
+ #
40
+ # Active Records accept constructor parameters either in a hash or as a block. The hash
41
+ # method is especially useful when you're receiving the data from somewhere else, like an
42
+ # HTTP request. It works like this:
43
+ #
44
+ # user = User.new(name: "David", occupation: "Code Artist")
45
+ # user.name # => "David"
46
+ #
47
+ # You can also use block initialization:
48
+ #
49
+ # user = User.new do |u|
50
+ # u.name = "David"
51
+ # u.occupation = "Code Artist"
52
+ # end
53
+ #
54
+ # And of course you can just create a bare object and specify the attributes after the fact:
55
+ #
56
+ # user = User.new
57
+ # user.name = "David"
58
+ # user.occupation = "Code Artist"
59
+ #
60
+ # == Conditions
61
+ #
62
+ # Conditions can either be specified as a string, array, or hash representing the WHERE-part of an SQL statement.
63
+ # The array form is to be used when the condition input is tainted and requires sanitization. The string form can
64
+ # be used for statements that don't involve tainted data. The hash form works much like the array form, except
65
+ # only equality and range is possible. Examples:
66
+ #
67
+ # class User < ActiveRecord::Base
68
+ # def self.authenticate_unsafely(user_name, password)
69
+ # where("user_name = '#{user_name}' AND password = '#{password}'").first
70
+ # end
71
+ #
72
+ # def self.authenticate_safely(user_name, password)
73
+ # where("user_name = ? AND password = ?", user_name, password).first
74
+ # end
75
+ #
76
+ # def self.authenticate_safely_simply(user_name, password)
77
+ # where(user_name: user_name, password: password).first
78
+ # end
79
+ # end
80
+ #
81
+ # The <tt>authenticate_unsafely</tt> method inserts the parameters directly into the query
82
+ # and is thus susceptible to SQL-injection attacks if the <tt>user_name</tt> and +password+
83
+ # parameters come directly from an HTTP request. The <tt>authenticate_safely</tt> and
84
+ # <tt>authenticate_safely_simply</tt> both will sanitize the <tt>user_name</tt> and +password+
85
+ # before inserting them in the query, which will ensure that an attacker can't escape the
86
+ # query and fake the login (or worse).
87
+ #
88
+ # When using multiple parameters in the conditions, it can easily become hard to read exactly
89
+ # what the fourth or fifth question mark is supposed to represent. In those cases, you can
90
+ # resort to named bind variables instead. That's done by replacing the question marks with
91
+ # symbols and supplying a hash with values for the matching symbol keys:
92
+ #
93
+ # Company.where(
94
+ # "id = :id AND name = :name AND division = :division AND created_at > :accounting_date",
95
+ # { id: 3, name: "37signals", division: "First", accounting_date: '2005-01-01' }
96
+ # ).first
97
+ #
98
+ # Similarly, a simple hash without a statement will generate conditions based on equality with the SQL AND
99
+ # operator. For instance:
100
+ #
101
+ # Student.where(first_name: "Harvey", status: 1)
102
+ # Student.where(params[:student])
103
+ #
104
+ # A range may be used in the hash to use the SQL BETWEEN operator:
105
+ #
106
+ # Student.where(grade: 9..12)
107
+ #
108
+ # An array may be used in the hash to use the SQL IN operator:
109
+ #
110
+ # Student.where(grade: [9,11,12])
111
+ #
112
+ # When joining tables, nested hashes or keys written in the form 'table_name.column_name'
113
+ # can be used to qualify the table name of a particular condition. For instance:
114
+ #
115
+ # Student.joins(:schools).where(schools: { category: 'public' })
116
+ # Student.joins(:schools).where('schools.category' => 'public' )
117
+ #
118
+ # == Overwriting default accessors
119
+ #
120
+ # All column values are automatically available through basic accessors on the Active Record
121
+ # object, but sometimes you want to specialize this behavior. This can be done by overwriting
122
+ # the default accessors (using the same name as the attribute) and calling
123
+ # +super+ to actually change things.
124
+ #
125
+ # class Song < ActiveRecord::Base
126
+ # # Uses an integer of seconds to hold the length of the song
127
+ #
128
+ # def length=(minutes)
129
+ # super(minutes.to_i * 60)
130
+ # end
131
+ #
132
+ # def length
133
+ # super / 60
134
+ # end
135
+ # end
136
+ #
137
+ # == Attribute query methods
138
+ #
139
+ # In addition to the basic accessors, query methods are also automatically available on the Active Record object.
140
+ # Query methods allow you to test whether an attribute value is present.
141
+ # Additionally, when dealing with numeric values, a query method will return false if the value is zero.
142
+ #
143
+ # For example, an Active Record User with the <tt>name</tt> attribute has a <tt>name?</tt> method that you can call
144
+ # to determine whether the user has a name:
145
+ #
146
+ # user = User.new(name: "David")
147
+ # user.name? # => true
148
+ #
149
+ # anonymous = User.new(name: "")
150
+ # anonymous.name? # => false
151
+ #
152
+ # == Accessing attributes before they have been typecasted
153
+ #
154
+ # Sometimes you want to be able to read the raw attribute data without having the column-determined
155
+ # typecast run its course first. That can be done by using the <tt><attribute>_before_type_cast</tt>
156
+ # accessors that all attributes have. For example, if your Account model has a <tt>balance</tt> attribute,
157
+ # you can call <tt>account.balance_before_type_cast</tt> or <tt>account.id_before_type_cast</tt>.
158
+ #
159
+ # This is especially useful in validation situations where the user might supply a string for an
160
+ # integer field and you want to display the original string back in an error message. Accessing the
161
+ # attribute normally would typecast the string to 0, which isn't what you want.
162
+ #
163
+ # == Dynamic attribute-based finders
164
+ #
165
+ # Dynamic attribute-based finders are a mildly deprecated way of getting (and/or creating) objects
166
+ # by simple queries without turning to SQL. They work by appending the name of an attribute
167
+ # to <tt>find_by_</tt> like <tt>Person.find_by_user_name</tt>.
168
+ # Instead of writing <tt>Person.find_by(user_name: user_name)</tt>, you can use
169
+ # <tt>Person.find_by_user_name(user_name)</tt>.
170
+ #
171
+ # It's possible to add an exclamation point (!) on the end of the dynamic finders to get them to raise an
172
+ # ActiveRecord::RecordNotFound error if they do not return any records,
173
+ # like <tt>Person.find_by_last_name!</tt>.
174
+ #
175
+ # It's also possible to use multiple attributes in the same <tt>find_by_</tt> by separating them with
176
+ # "_and_".
177
+ #
178
+ # Person.find_by(user_name: user_name, password: password)
179
+ # Person.find_by_user_name_and_password(user_name, password) # with dynamic finder
180
+ #
181
+ # It's even possible to call these dynamic finder methods on relations and named scopes.
182
+ #
183
+ # Payment.order("created_on").find_by_amount(50)
184
+ #
185
+ # == Saving arrays, hashes, and other non-mappable objects in text columns
186
+ #
187
+ # Active Record can serialize any object in text columns using YAML. To do so, you must
188
+ # specify this with a call to the class method
189
+ # {serialize}[rdoc-ref:AttributeMethods::Serialization::ClassMethods#serialize].
190
+ # This makes it possible to store arrays, hashes, and other non-mappable objects without doing
191
+ # any additional work.
192
+ #
193
+ # class User < ActiveRecord::Base
194
+ # serialize :preferences
195
+ # end
196
+ #
197
+ # user = User.create(preferences: { "background" => "black", "display" => large })
198
+ # User.find(user.id).preferences # => { "background" => "black", "display" => large }
199
+ #
200
+ # You can also specify a class option as the second parameter that'll raise an exception
201
+ # if a serialized object is retrieved as a descendant of a class not in the hierarchy.
202
+ #
203
+ # class User < ActiveRecord::Base
204
+ # serialize :preferences, Hash
205
+ # end
206
+ #
207
+ # user = User.create(preferences: %w( one two three ))
208
+ # User.find(user.id).preferences # raises SerializationTypeMismatch
209
+ #
210
+ # When you specify a class option, the default value for that attribute will be a new
211
+ # instance of that class.
212
+ #
213
+ # class User < ActiveRecord::Base
214
+ # serialize :preferences, OpenStruct
215
+ # end
216
+ #
217
+ # user = User.new
218
+ # user.preferences.theme_color = "red"
219
+ #
220
+ #
221
+ # == Single table inheritance
222
+ #
223
+ # Active Record allows inheritance by storing the name of the class in a
224
+ # column that is named "type" by default. See ActiveRecord::Inheritance for
225
+ # more details.
226
+ #
227
+ # == Connection to multiple databases in different models
228
+ #
229
+ # Connections are usually created through
230
+ # {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection] and retrieved
231
+ # by ActiveRecord::Base.connection. All classes inheriting from ActiveRecord::Base will use this
232
+ # connection. But you can also set a class-specific connection. For example, if Course is an
233
+ # ActiveRecord::Base, but resides in a different database, you can just say <tt>Course.establish_connection</tt>
234
+ # and Course and all of its subclasses will use this connection instead.
235
+ #
236
+ # This feature is implemented by keeping a connection pool in ActiveRecord::Base that is
237
+ # a hash indexed by the class. If a connection is requested, the
238
+ # {ActiveRecord::Base.retrieve_connection}[rdoc-ref:ConnectionHandling#retrieve_connection] method
239
+ # will go up the class-hierarchy until a connection is found in the connection pool.
240
+ #
241
+ # == Exceptions
242
+ #
243
+ # * ActiveRecordError - Generic error class and superclass of all other errors raised by Active Record.
244
+ # * AdapterNotSpecified - The configuration hash used in
245
+ # {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection]
246
+ # didn't include an <tt>:adapter</tt> key.
247
+ # * AdapterNotFound - The <tt>:adapter</tt> key used in
248
+ # {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection]
249
+ # specified a non-existent adapter
250
+ # (or a bad spelling of an existing one).
251
+ # * AssociationTypeMismatch - The object assigned to the association wasn't of the type
252
+ # specified in the association definition.
253
+ # * AttributeAssignmentError - An error occurred while doing a mass assignment through the
254
+ # {ActiveRecord::Base#attributes=}[rdoc-ref:AttributeAssignment#attributes=] method.
255
+ # You can inspect the +attribute+ property of the exception object to determine which attribute
256
+ # triggered the error.
257
+ # * ConnectionNotEstablished - No connection has been established.
258
+ # Use {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection] before querying.
259
+ # * MultiparameterAssignmentErrors - Collection of errors that occurred during a mass assignment using the
260
+ # {ActiveRecord::Base#attributes=}[rdoc-ref:AttributeAssignment#attributes=] method.
261
+ # The +errors+ property of this exception contains an array of
262
+ # AttributeAssignmentError
263
+ # objects that should be inspected to determine which attributes triggered the errors.
264
+ # * RecordInvalid - raised by {ActiveRecord::Base#save!}[rdoc-ref:Persistence#save!] and
265
+ # {ActiveRecord::Base.create!}[rdoc-ref:Persistence::ClassMethods#create!]
266
+ # when the record is invalid.
267
+ # * RecordNotFound - No record responded to the {ActiveRecord::Base.find}[rdoc-ref:FinderMethods#find] method.
268
+ # Either the row with the given ID doesn't exist or the row didn't meet the additional restrictions.
269
+ # Some {ActiveRecord::Base.find}[rdoc-ref:FinderMethods#find] calls do not raise this exception to signal
270
+ # nothing was found, please check its documentation for further details.
271
+ # * SerializationTypeMismatch - The serialized object wasn't of the class specified as the second parameter.
272
+ # * StatementInvalid - The database server rejected the SQL statement. The precise error is added in the message.
273
+ #
274
+ # *Note*: The attributes listed are class-level attributes (accessible from both the class and instance level).
275
+ # So it's possible to assign a logger to the class through <tt>Base.logger=</tt> which will then be used by all
276
+ # instances in the current object space.
277
+ class Base
278
+ extend ActiveModel::Naming
279
+
280
+ extend ActiveSupport::Benchmarkable
281
+ extend ActiveSupport::DescendantsTracker
282
+
283
+ extend ConnectionHandling
284
+ extend QueryCache::ClassMethods
285
+ extend Querying
286
+ extend Translation
287
+ extend DynamicMatchers
288
+ extend Explain
289
+ extend Enum
290
+ extend Delegation::DelegateCache
291
+ extend Aggregations::ClassMethods
292
+
293
+ include Core
294
+ include Persistence
295
+ include ReadonlyAttributes
296
+ include ModelSchema
297
+ include Inheritance
298
+ include Scoping
299
+ include Sanitization
300
+ include AttributeAssignment
301
+ include ActiveModel::Conversion
302
+ include Integration
303
+ include Validations
304
+ include CounterCache
305
+ include Attributes
306
+ include AttributeDecorators
307
+ include Locking::Optimistic
308
+ include Locking::Pessimistic
309
+ include DefineCallbacks
310
+ include AttributeMethods
311
+ include Callbacks
312
+ include Timestamp
313
+ include Associations
314
+ include ActiveModel::SecurePassword
315
+ include AutosaveAssociation
316
+ include NestedAttributes
317
+ include Transactions
318
+ include TouchLater
319
+ include NoTouching
320
+ include Reflection
321
+ include Serialization
322
+ include Store
323
+ include SecureToken
324
+ include Suppressor
325
+ end
326
+
327
+ ActiveSupport.run_load_hooks(:active_record, Base)
328
+ end
@@ -0,0 +1,339 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ # = Active Record \Callbacks
5
+ #
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
8
+ # dependent objects are deleted when {ActiveRecord::Base#destroy}[rdoc-ref:Persistence#destroy] is called (by overwriting +before_destroy+) or
9
+ # to massage attributes before they're validated (by overwriting +before_validation+).
10
+ # As an example of the callbacks initiated, consider the {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] call for a new record:
11
+ #
12
+ # * (-) <tt>save</tt>
13
+ # * (-) <tt>valid</tt>
14
+ # * (1) <tt>before_validation</tt>
15
+ # * (-) <tt>validate</tt>
16
+ # * (2) <tt>after_validation</tt>
17
+ # * (3) <tt>before_save</tt>
18
+ # * (4) <tt>before_create</tt>
19
+ # * (-) <tt>create</tt>
20
+ # * (5) <tt>after_create</tt>
21
+ # * (6) <tt>after_save</tt>
22
+ # * (7) <tt>after_commit</tt>
23
+ #
24
+ # Also, an <tt>after_rollback</tt> callback can be configured to be triggered whenever a rollback is issued.
25
+ # Check out ActiveRecord::Transactions for more details about <tt>after_commit</tt> and
26
+ # <tt>after_rollback</tt>.
27
+ #
28
+ # Additionally, an <tt>after_touch</tt> callback is triggered whenever an
29
+ # object is touched.
30
+ #
31
+ # Lastly an <tt>after_find</tt> and <tt>after_initialize</tt> callback is triggered for each object that
32
+ # is found and instantiated by a finder, with <tt>after_initialize</tt> being triggered after new objects
33
+ # are instantiated as well.
34
+ #
35
+ # There are nineteen callbacks in total, which give you immense power to react and prepare for each state in the
36
+ # Active Record life cycle. The sequence for calling {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] for an existing record is similar,
37
+ # except that each <tt>_create</tt> callback is replaced by the corresponding <tt>_update</tt> callback.
38
+ #
39
+ # Examples:
40
+ # class CreditCard < ActiveRecord::Base
41
+ # # Strip everything but digits, so the user can specify "555 234 34" or
42
+ # # "5552-3434" and both will mean "55523434"
43
+ # before_validation(on: :create) do
44
+ # self.number = number.gsub(/[^0-9]/, "") if attribute_present?("number")
45
+ # end
46
+ # end
47
+ #
48
+ # class Subscription < ActiveRecord::Base
49
+ # before_create :record_signup
50
+ #
51
+ # private
52
+ # def record_signup
53
+ # self.signed_up_on = Date.today
54
+ # end
55
+ # end
56
+ #
57
+ # class Firm < ActiveRecord::Base
58
+ # # Disables access to the system, for associated clients and people when the firm is destroyed
59
+ # before_destroy { |record| Person.where(firm_id: record.id).update_all(access: 'disabled') }
60
+ # before_destroy { |record| Client.where(client_of: record.id).update_all(access: 'disabled') }
61
+ # end
62
+ #
63
+ # == Inheritable callback queues
64
+ #
65
+ # Besides the overwritable callback methods, it's also possible to register callbacks through the
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.
68
+ #
69
+ # class Topic < ActiveRecord::Base
70
+ # before_destroy :destroy_author
71
+ # end
72
+ #
73
+ # class Reply < Topic
74
+ # before_destroy :destroy_readers
75
+ # end
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.
79
+ #
80
+ # *IMPORTANT:* In order for inheritance to work for the callback queues, you must specify the
81
+ # callbacks before specifying the associations. Otherwise, you might trigger the loading of a
82
+ # child before the parent has registered the callbacks and they won't be inherited.
83
+ #
84
+ # == Types of callbacks
85
+ #
86
+ # There are four types of callbacks accepted by the callback macros: Method references (symbol), callback objects,
87
+ # inline methods (using a proc). Method references and callback objects
88
+ # are the recommended approaches, inline methods using a proc are sometimes appropriate (such as for
89
+ # creating mix-ins).
90
+ #
91
+ # The method reference callbacks work by specifying a protected or private method available in the object, like this:
92
+ #
93
+ # class Topic < ActiveRecord::Base
94
+ # before_destroy :delete_parents
95
+ #
96
+ # private
97
+ # def delete_parents
98
+ # self.class.delete_by(parent_id: id)
99
+ # end
100
+ # end
101
+ #
102
+ # The callback objects have methods named after the callback called with the record as the only parameter, such as:
103
+ #
104
+ # class BankAccount < ActiveRecord::Base
105
+ # before_save EncryptionWrapper.new
106
+ # after_save EncryptionWrapper.new
107
+ # after_initialize EncryptionWrapper.new
108
+ # end
109
+ #
110
+ # class EncryptionWrapper
111
+ # def before_save(record)
112
+ # record.credit_card_number = encrypt(record.credit_card_number)
113
+ # end
114
+ #
115
+ # def after_save(record)
116
+ # record.credit_card_number = decrypt(record.credit_card_number)
117
+ # end
118
+ #
119
+ # alias_method :after_initialize, :after_save
120
+ #
121
+ # private
122
+ # def encrypt(value)
123
+ # # Secrecy is committed
124
+ # end
125
+ #
126
+ # def decrypt(value)
127
+ # # Secrecy is unveiled
128
+ # end
129
+ # end
130
+ #
131
+ # So you specify the object you want to be messaged on a given callback. When that callback is triggered, the object has
132
+ # a method by the name of the callback messaged. You can make these callbacks more flexible by passing in other
133
+ # initialization data such as the name of the attribute to work with:
134
+ #
135
+ # class BankAccount < ActiveRecord::Base
136
+ # before_save EncryptionWrapper.new("credit_card_number")
137
+ # after_save EncryptionWrapper.new("credit_card_number")
138
+ # after_initialize EncryptionWrapper.new("credit_card_number")
139
+ # end
140
+ #
141
+ # class EncryptionWrapper
142
+ # def initialize(attribute)
143
+ # @attribute = attribute
144
+ # end
145
+ #
146
+ # def before_save(record)
147
+ # record.send("#{@attribute}=", encrypt(record.send("#{@attribute}")))
148
+ # end
149
+ #
150
+ # def after_save(record)
151
+ # record.send("#{@attribute}=", decrypt(record.send("#{@attribute}")))
152
+ # end
153
+ #
154
+ # alias_method :after_initialize, :after_save
155
+ #
156
+ # private
157
+ # def encrypt(value)
158
+ # # Secrecy is committed
159
+ # end
160
+ #
161
+ # def decrypt(value)
162
+ # # Secrecy is unveiled
163
+ # end
164
+ # end
165
+ #
166
+ # == <tt>before_validation*</tt> returning statements
167
+ #
168
+ # If the +before_validation+ callback throws +:abort+, the process will be
169
+ # aborted and {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] will return +false+.
170
+ # If {ActiveRecord::Base#save!}[rdoc-ref:Persistence#save!] is called it will raise an ActiveRecord::RecordInvalid exception.
171
+ # Nothing will be appended to the errors object.
172
+ #
173
+ # == Canceling callbacks
174
+ #
175
+ # If a <tt>before_*</tt> callback throws +:abort+, all the later callbacks and
176
+ # the associated action are cancelled.
177
+ # Callbacks are generally run in the order they are defined, with the exception of callbacks defined as
178
+ # methods on the model, which are called last.
179
+ #
180
+ # == Ordering callbacks
181
+ #
182
+ # Sometimes the code needs that the callbacks execute in a specific order. For example, a +before_destroy+
183
+ # callback (+log_children+ in this case) should be executed before the children get destroyed by the
184
+ # <tt>dependent: :destroy</tt> option.
185
+ #
186
+ # Let's look at the code below:
187
+ #
188
+ # class Topic < ActiveRecord::Base
189
+ # has_many :children, dependent: :destroy
190
+ #
191
+ # before_destroy :log_children
192
+ #
193
+ # private
194
+ # def log_children
195
+ # # Child processing
196
+ # end
197
+ # end
198
+ #
199
+ # In this case, the problem is that when the +before_destroy+ callback is executed, the children are not available
200
+ # because the {ActiveRecord::Base#destroy}[rdoc-ref:Persistence#destroy] callback gets executed first.
201
+ # You can use the +prepend+ option on the +before_destroy+ callback to avoid this.
202
+ #
203
+ # class Topic < ActiveRecord::Base
204
+ # has_many :children, dependent: :destroy
205
+ #
206
+ # before_destroy :log_children, prepend: true
207
+ #
208
+ # private
209
+ # def log_children
210
+ # # Child processing
211
+ # end
212
+ # end
213
+ #
214
+ # This way, the +before_destroy+ gets executed before the <tt>dependent: :destroy</tt> is called, and the data is still available.
215
+ #
216
+ # Also, there are cases when you want several callbacks of the same type to
217
+ # be executed in order.
218
+ #
219
+ # For example:
220
+ #
221
+ # class Topic < ActiveRecord::Base
222
+ # has_many :children
223
+ #
224
+ # after_save :log_children
225
+ # after_save :do_something_else
226
+ #
227
+ # private
228
+ #
229
+ # def log_children
230
+ # # Child processing
231
+ # end
232
+ #
233
+ # def do_something_else
234
+ # # Something else
235
+ # end
236
+ # end
237
+ #
238
+ # In this case the +log_children+ gets executed before +do_something_else+.
239
+ # The same applies to all non-transactional callbacks.
240
+ #
241
+ # In case there are multiple transactional callbacks as seen below, the order
242
+ # is reversed.
243
+ #
244
+ # For example:
245
+ #
246
+ # class Topic < ActiveRecord::Base
247
+ # has_many :children
248
+ #
249
+ # after_commit :log_children
250
+ # after_commit :do_something_else
251
+ #
252
+ # private
253
+ #
254
+ # def log_children
255
+ # # Child processing
256
+ # end
257
+ #
258
+ # def do_something_else
259
+ # # Something else
260
+ # end
261
+ # end
262
+ #
263
+ # In this case the +do_something_else+ gets executed before +log_children+.
264
+ #
265
+ # == \Transactions
266
+ #
267
+ # The entire callback chain of a {#save}[rdoc-ref:Persistence#save], {#save!}[rdoc-ref:Persistence#save!],
268
+ # or {#destroy}[rdoc-ref:Persistence#destroy] call runs within a transaction. That includes <tt>after_*</tt> hooks.
269
+ # If everything goes fine a COMMIT is executed once the chain has been completed.
270
+ #
271
+ # If a <tt>before_*</tt> callback cancels the action a ROLLBACK is issued. You
272
+ # can also trigger a ROLLBACK raising an exception in any of the callbacks,
273
+ # including <tt>after_*</tt> hooks. Note, however, that in that case the client
274
+ # needs to be aware of it because an ordinary {#save}[rdoc-ref:Persistence#save] will raise such exception
275
+ # instead of quietly returning +false+.
276
+ #
277
+ # == Debugging callbacks
278
+ #
279
+ # The callback chain is accessible via the <tt>_*_callbacks</tt> method on an object. Active Model \Callbacks support
280
+ # <tt>:before</tt>, <tt>:after</tt> and <tt>:around</tt> as values for the <tt>kind</tt> property. The <tt>kind</tt> property
281
+ # defines what part of the chain the callback runs in.
282
+ #
283
+ # To find all callbacks in the before_save callback chain:
284
+ #
285
+ # Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }
286
+ #
287
+ # Returns an array of callback objects that form the before_save chain.
288
+ #
289
+ # 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:
290
+ #
291
+ # Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }.collect(&:filter).include?(:rest_when_dead)
292
+ #
293
+ # Returns true or false depending on whether the proc is contained in the before_save callback chain on a Topic model.
294
+ #
295
+ module Callbacks
296
+ extend ActiveSupport::Concern
297
+
298
+ CALLBACKS = [
299
+ :after_initialize, :after_find, :after_touch, :before_validation, :after_validation,
300
+ :before_save, :around_save, :after_save, :before_create, :around_create,
301
+ :after_create, :before_update, :around_update, :after_update,
302
+ :before_destroy, :around_destroy, :after_destroy, :after_commit, :after_rollback
303
+ ]
304
+
305
+ def destroy #:nodoc:
306
+ @_destroy_callback_already_called ||= false
307
+ return if @_destroy_callback_already_called
308
+ @_destroy_callback_already_called = true
309
+ _run_destroy_callbacks { super }
310
+ rescue RecordNotDestroyed => e
311
+ @_association_destroy_exception = e
312
+ false
313
+ ensure
314
+ @_destroy_callback_already_called = false
315
+ end
316
+
317
+ def touch(*) #:nodoc:
318
+ _run_touch_callbacks { super }
319
+ end
320
+
321
+ def increment!(attribute, by = 1, touch: nil) # :nodoc:
322
+ touch ? _run_touch_callbacks { super } : super
323
+ end
324
+
325
+ private
326
+
327
+ def create_or_update(**)
328
+ _run_save_callbacks { super }
329
+ end
330
+
331
+ def _create_record
332
+ _run_create_callbacks { super }
333
+ end
334
+
335
+ def _update_record
336
+ _run_update_callbacks { super }
337
+ end
338
+ end
339
+ end