activerecord 4.2.0 → 6.1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (374) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1221 -796
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +15 -14
  5. data/examples/performance.rb +33 -32
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/aggregations.rb +267 -249
  8. data/lib/active_record/association_relation.rb +45 -7
  9. data/lib/active_record/associations/alias_tracker.rb +40 -43
  10. data/lib/active_record/associations/association.rb +172 -67
  11. data/lib/active_record/associations/association_scope.rb +105 -129
  12. data/lib/active_record/associations/belongs_to_association.rb +85 -59
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
  14. data/lib/active_record/associations/builder/association.rb +57 -43
  15. data/lib/active_record/associations/builder/belongs_to.rb +74 -57
  16. data/lib/active_record/associations/builder/collection_association.rb +15 -33
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +57 -70
  18. data/lib/active_record/associations/builder/has_many.rb +13 -5
  19. data/lib/active_record/associations/builder/has_one.rb +44 -6
  20. data/lib/active_record/associations/builder/singular_association.rb +16 -10
  21. data/lib/active_record/associations/collection_association.rb +168 -279
  22. data/lib/active_record/associations/collection_proxy.rb +263 -155
  23. data/lib/active_record/associations/foreign_association.rb +33 -0
  24. data/lib/active_record/associations/has_many_association.rb +57 -84
  25. data/lib/active_record/associations/has_many_through_association.rb +70 -82
  26. data/lib/active_record/associations/has_one_association.rb +74 -47
  27. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  28. data/lib/active_record/associations/join_dependency/join_association.rb +54 -73
  29. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  31. data/lib/active_record/associations/join_dependency.rb +175 -164
  32. data/lib/active_record/associations/preloader/association.rb +107 -112
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  34. data/lib/active_record/associations/preloader.rb +99 -96
  35. data/lib/active_record/associations/singular_association.rb +18 -45
  36. data/lib/active_record/associations/through_association.rb +49 -24
  37. data/lib/active_record/associations.rb +1845 -1597
  38. data/lib/active_record/attribute_assignment.rb +59 -185
  39. data/lib/active_record/attribute_methods/before_type_cast.rb +20 -7
  40. data/lib/active_record/attribute_methods/dirty.rb +168 -138
  41. data/lib/active_record/attribute_methods/primary_key.rb +93 -83
  42. data/lib/active_record/attribute_methods/query.rb +8 -10
  43. data/lib/active_record/attribute_methods/read.rb +19 -79
  44. data/lib/active_record/attribute_methods/serialization.rb +49 -24
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +59 -36
  46. data/lib/active_record/attribute_methods/write.rb +25 -56
  47. data/lib/active_record/attribute_methods.rb +153 -162
  48. data/lib/active_record/attributes.rb +234 -70
  49. data/lib/active_record/autosave_association.rb +157 -69
  50. data/lib/active_record/base.rb +49 -50
  51. data/lib/active_record/callbacks.rb +234 -79
  52. data/lib/active_record/coders/json.rb +3 -1
  53. data/lib/active_record/coders/yaml_column.rb +46 -13
  54. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -317
  55. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
  56. data/lib/active_record/connection_adapters/abstract/database_statements.rb +301 -113
  57. data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
  58. data/lib/active_record/connection_adapters/abstract/quoting.rb +187 -60
  59. data/lib/active_record/connection_adapters/abstract/savepoints.rb +9 -7
  60. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
  61. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +485 -253
  62. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  63. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +909 -263
  64. data/lib/active_record/connection_adapters/abstract/transaction.rb +254 -92
  65. data/lib/active_record/connection_adapters/abstract_adapter.rb +492 -221
  66. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +580 -608
  67. data/lib/active_record/connection_adapters/column.rb +67 -40
  68. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  69. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  70. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  71. data/lib/active_record/connection_adapters/mysql/database_statements.rb +196 -0
  72. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
  73. data/lib/active_record/connection_adapters/mysql/quoting.rb +96 -0
  74. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +97 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +103 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +91 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +271 -0
  78. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
  79. data/lib/active_record/connection_adapters/mysql2_adapter.rb +81 -199
  80. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  81. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +44 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +78 -161
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -57
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +5 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +8 -6
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +17 -13
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +6 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -20
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  98. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  101. data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +67 -51
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  109. data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -25
  110. data/lib/active_record/connection_adapters/postgresql/quoting.rb +171 -48
  111. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  112. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
  114. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
  115. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +499 -293
  116. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
  117. data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
  118. data/lib/active_record/connection_adapters/postgresql_adapter.rb +595 -382
  119. data/lib/active_record/connection_adapters/schema_cache.rb +191 -29
  120. data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
  121. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -0
  122. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  123. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +21 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  126. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  127. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
  128. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +322 -389
  129. data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
  130. data/lib/active_record/connection_adapters.rb +52 -0
  131. data/lib/active_record/connection_handling.rb +314 -41
  132. data/lib/active_record/core.rb +488 -243
  133. data/lib/active_record/counter_cache.rb +71 -50
  134. data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
  135. data/lib/active_record/database_configurations/database_config.rb +80 -0
  136. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  137. data/lib/active_record/database_configurations/url_config.rb +53 -0
  138. data/lib/active_record/database_configurations.rb +273 -0
  139. data/lib/active_record/delegated_type.rb +209 -0
  140. data/lib/active_record/destroy_association_async_job.rb +36 -0
  141. data/lib/active_record/dynamic_matchers.rb +87 -106
  142. data/lib/active_record/enum.rb +212 -94
  143. data/lib/active_record/errors.rb +225 -54
  144. data/lib/active_record/explain.rb +27 -11
  145. data/lib/active_record/explain_registry.rb +4 -2
  146. data/lib/active_record/explain_subscriber.rb +11 -6
  147. data/lib/active_record/fixture_set/file.rb +33 -14
  148. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  149. data/lib/active_record/fixture_set/render_context.rb +17 -0
  150. data/lib/active_record/fixture_set/table_row.rb +152 -0
  151. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  152. data/lib/active_record/fixtures.rb +273 -496
  153. data/lib/active_record/gem_version.rb +6 -4
  154. data/lib/active_record/inheritance.rb +175 -110
  155. data/lib/active_record/insert_all.rb +212 -0
  156. data/lib/active_record/integration.rb +121 -29
  157. data/lib/active_record/internal_metadata.rb +64 -0
  158. data/lib/active_record/legacy_yaml_adapter.rb +52 -0
  159. data/lib/active_record/locale/en.yml +3 -2
  160. data/lib/active_record/locking/optimistic.rb +103 -95
  161. data/lib/active_record/locking/pessimistic.rb +22 -6
  162. data/lib/active_record/log_subscriber.rb +93 -31
  163. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  164. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  165. data/lib/active_record/middleware/database_selector.rb +77 -0
  166. data/lib/active_record/migration/command_recorder.rb +185 -90
  167. data/lib/active_record/migration/compatibility.rb +298 -0
  168. data/lib/active_record/migration/join_table.rb +8 -7
  169. data/lib/active_record/migration.rb +685 -309
  170. data/lib/active_record/model_schema.rb +420 -113
  171. data/lib/active_record/nested_attributes.rb +265 -216
  172. data/lib/active_record/no_touching.rb +15 -2
  173. data/lib/active_record/null_relation.rb +24 -38
  174. data/lib/active_record/persistence.rb +574 -135
  175. data/lib/active_record/query_cache.rb +29 -23
  176. data/lib/active_record/querying.rb +50 -31
  177. data/lib/active_record/railtie.rb +175 -54
  178. data/lib/active_record/railties/console_sandbox.rb +3 -3
  179. data/lib/active_record/railties/controller_runtime.rb +34 -33
  180. data/lib/active_record/railties/databases.rake +533 -216
  181. data/lib/active_record/readonly_attributes.rb +9 -4
  182. data/lib/active_record/reflection.rb +485 -310
  183. data/lib/active_record/relation/batches/batch_enumerator.rb +85 -0
  184. data/lib/active_record/relation/batches.rb +217 -59
  185. data/lib/active_record/relation/calculations.rb +326 -244
  186. data/lib/active_record/relation/delegation.rb +76 -84
  187. data/lib/active_record/relation/finder_methods.rb +318 -256
  188. data/lib/active_record/relation/from_clause.rb +30 -0
  189. data/lib/active_record/relation/merger.rb +99 -84
  190. data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -25
  191. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
  192. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  193. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +57 -0
  194. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  195. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  196. data/lib/active_record/relation/predicate_builder.rb +139 -96
  197. data/lib/active_record/relation/query_attribute.rb +50 -0
  198. data/lib/active_record/relation/query_methods.rb +757 -409
  199. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  200. data/lib/active_record/relation/spawn_methods.rb +23 -21
  201. data/lib/active_record/relation/where_clause.rb +239 -0
  202. data/lib/active_record/relation.rb +554 -342
  203. data/lib/active_record/result.rb +91 -47
  204. data/lib/active_record/runtime_registry.rb +6 -4
  205. data/lib/active_record/sanitization.rb +134 -122
  206. data/lib/active_record/schema.rb +21 -24
  207. data/lib/active_record/schema_dumper.rb +141 -92
  208. data/lib/active_record/schema_migration.rb +24 -26
  209. data/lib/active_record/scoping/default.rb +96 -82
  210. data/lib/active_record/scoping/named.rb +78 -36
  211. data/lib/active_record/scoping.rb +45 -27
  212. data/lib/active_record/secure_token.rb +48 -0
  213. data/lib/active_record/serialization.rb +8 -6
  214. data/lib/active_record/signed_id.rb +116 -0
  215. data/lib/active_record/statement_cache.rb +89 -36
  216. data/lib/active_record/store.rb +133 -43
  217. data/lib/active_record/suppressor.rb +61 -0
  218. data/lib/active_record/table_metadata.rb +81 -0
  219. data/lib/active_record/tasks/database_tasks.rb +366 -129
  220. data/lib/active_record/tasks/mysql_database_tasks.rb +68 -100
  221. data/lib/active_record/tasks/postgresql_database_tasks.rb +87 -39
  222. data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -19
  223. data/lib/active_record/test_databases.rb +24 -0
  224. data/lib/active_record/test_fixtures.rb +291 -0
  225. data/lib/active_record/timestamp.rb +86 -43
  226. data/lib/active_record/touch_later.rb +65 -0
  227. data/lib/active_record/transactions.rb +181 -152
  228. data/lib/active_record/translation.rb +3 -1
  229. data/lib/active_record/type/adapter_specific_registry.rb +126 -0
  230. data/lib/active_record/type/date.rb +4 -41
  231. data/lib/active_record/type/date_time.rb +4 -38
  232. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  233. data/lib/active_record/type/hash_lookup_type_map.rb +12 -5
  234. data/lib/active_record/type/internal/timezone.rb +17 -0
  235. data/lib/active_record/type/json.rb +30 -0
  236. data/lib/active_record/type/serialized.rb +33 -15
  237. data/lib/active_record/type/text.rb +2 -2
  238. data/lib/active_record/type/time.rb +21 -16
  239. data/lib/active_record/type/type_map.rb +16 -19
  240. data/lib/active_record/type/unsigned_integer.rb +9 -8
  241. data/lib/active_record/type.rb +84 -23
  242. data/lib/active_record/type_caster/connection.rb +33 -0
  243. data/lib/active_record/type_caster/map.rb +23 -0
  244. data/lib/active_record/type_caster.rb +9 -0
  245. data/lib/active_record/validations/absence.rb +25 -0
  246. data/lib/active_record/validations/associated.rb +12 -4
  247. data/lib/active_record/validations/length.rb +26 -0
  248. data/lib/active_record/validations/numericality.rb +35 -0
  249. data/lib/active_record/validations/presence.rb +14 -13
  250. data/lib/active_record/validations/uniqueness.rb +65 -48
  251. data/lib/active_record/validations.rb +39 -35
  252. data/lib/active_record/version.rb +3 -1
  253. data/lib/active_record.rb +44 -28
  254. data/lib/arel/alias_predication.rb +9 -0
  255. data/lib/arel/attributes/attribute.rb +41 -0
  256. data/lib/arel/collectors/bind.rb +29 -0
  257. data/lib/arel/collectors/composite.rb +39 -0
  258. data/lib/arel/collectors/plain_string.rb +20 -0
  259. data/lib/arel/collectors/sql_string.rb +27 -0
  260. data/lib/arel/collectors/substitute_binds.rb +35 -0
  261. data/lib/arel/crud.rb +42 -0
  262. data/lib/arel/delete_manager.rb +18 -0
  263. data/lib/arel/errors.rb +9 -0
  264. data/lib/arel/expressions.rb +29 -0
  265. data/lib/arel/factory_methods.rb +49 -0
  266. data/lib/arel/insert_manager.rb +49 -0
  267. data/lib/arel/math.rb +45 -0
  268. data/lib/arel/nodes/and.rb +32 -0
  269. data/lib/arel/nodes/ascending.rb +23 -0
  270. data/lib/arel/nodes/binary.rb +126 -0
  271. data/lib/arel/nodes/bind_param.rb +44 -0
  272. data/lib/arel/nodes/case.rb +55 -0
  273. data/lib/arel/nodes/casted.rb +62 -0
  274. data/lib/arel/nodes/comment.rb +29 -0
  275. data/lib/arel/nodes/count.rb +12 -0
  276. data/lib/arel/nodes/delete_statement.rb +45 -0
  277. data/lib/arel/nodes/descending.rb +23 -0
  278. data/lib/arel/nodes/equality.rb +15 -0
  279. data/lib/arel/nodes/extract.rb +24 -0
  280. data/lib/arel/nodes/false.rb +16 -0
  281. data/lib/arel/nodes/full_outer_join.rb +8 -0
  282. data/lib/arel/nodes/function.rb +44 -0
  283. data/lib/arel/nodes/grouping.rb +11 -0
  284. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  285. data/lib/arel/nodes/in.rb +15 -0
  286. data/lib/arel/nodes/infix_operation.rb +92 -0
  287. data/lib/arel/nodes/inner_join.rb +8 -0
  288. data/lib/arel/nodes/insert_statement.rb +37 -0
  289. data/lib/arel/nodes/join_source.rb +20 -0
  290. data/lib/arel/nodes/matches.rb +18 -0
  291. data/lib/arel/nodes/named_function.rb +23 -0
  292. data/lib/arel/nodes/node.rb +51 -0
  293. data/lib/arel/nodes/node_expression.rb +13 -0
  294. data/lib/arel/nodes/ordering.rb +27 -0
  295. data/lib/arel/nodes/outer_join.rb +8 -0
  296. data/lib/arel/nodes/over.rb +15 -0
  297. data/lib/arel/nodes/regexp.rb +16 -0
  298. data/lib/arel/nodes/right_outer_join.rb +8 -0
  299. data/lib/arel/nodes/select_core.rb +67 -0
  300. data/lib/arel/nodes/select_statement.rb +41 -0
  301. data/lib/arel/nodes/sql_literal.rb +19 -0
  302. data/lib/arel/nodes/string_join.rb +11 -0
  303. data/lib/arel/nodes/table_alias.rb +31 -0
  304. data/lib/arel/nodes/terminal.rb +16 -0
  305. data/lib/arel/nodes/true.rb +16 -0
  306. data/lib/arel/nodes/unary.rb +44 -0
  307. data/lib/arel/nodes/unary_operation.rb +20 -0
  308. data/lib/arel/nodes/unqualified_column.rb +22 -0
  309. data/lib/arel/nodes/update_statement.rb +41 -0
  310. data/lib/arel/nodes/values_list.rb +9 -0
  311. data/lib/arel/nodes/window.rb +126 -0
  312. data/lib/arel/nodes/with.rb +11 -0
  313. data/lib/arel/nodes.rb +70 -0
  314. data/lib/arel/order_predications.rb +13 -0
  315. data/lib/arel/predications.rb +250 -0
  316. data/lib/arel/select_manager.rb +270 -0
  317. data/lib/arel/table.rb +118 -0
  318. data/lib/arel/tree_manager.rb +72 -0
  319. data/lib/arel/update_manager.rb +34 -0
  320. data/lib/arel/visitors/dot.rb +308 -0
  321. data/lib/arel/visitors/mysql.rb +93 -0
  322. data/lib/arel/visitors/postgresql.rb +120 -0
  323. data/lib/arel/visitors/sqlite.rb +38 -0
  324. data/lib/arel/visitors/to_sql.rb +899 -0
  325. data/lib/arel/visitors/visitor.rb +45 -0
  326. data/lib/arel/visitors.rb +13 -0
  327. data/lib/arel/window_predications.rb +9 -0
  328. data/lib/arel.rb +54 -0
  329. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  330. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  331. data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -37
  332. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +26 -0
  333. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +13 -10
  334. data/lib/rails/generators/active_record/migration.rb +35 -1
  335. data/lib/rails/generators/active_record/model/model_generator.rb +55 -22
  336. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  337. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  338. data/lib/rails/generators/active_record.rb +7 -5
  339. metadata +175 -65
  340. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  341. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  342. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  343. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  344. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  345. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  346. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  347. data/lib/active_record/attribute.rb +0 -149
  348. data/lib/active_record/attribute_decorators.rb +0 -66
  349. data/lib/active_record/attribute_set/builder.rb +0 -86
  350. data/lib/active_record/attribute_set.rb +0 -77
  351. data/lib/active_record/connection_adapters/connection_specification.rb +0 -275
  352. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  353. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  354. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  355. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  356. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  357. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  358. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  359. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  360. data/lib/active_record/type/big_integer.rb +0 -13
  361. data/lib/active_record/type/binary.rb +0 -50
  362. data/lib/active_record/type/boolean.rb +0 -30
  363. data/lib/active_record/type/decimal.rb +0 -40
  364. data/lib/active_record/type/decorator.rb +0 -14
  365. data/lib/active_record/type/float.rb +0 -19
  366. data/lib/active_record/type/integer.rb +0 -55
  367. data/lib/active_record/type/mutable.rb +0 -16
  368. data/lib/active_record/type/numeric.rb +0 -36
  369. data/lib/active_record/type/string.rb +0 -36
  370. data/lib/active_record/type/time_value.rb +0 -38
  371. data/lib/active_record/type/value.rb +0 -101
  372. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -22
  373. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
  374. /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # = Active Record Autosave Association
3
5
  #
4
- # +AutosaveAssociation+ is a module that takes care of automatically saving
6
+ # AutosaveAssociation is a module that takes care of automatically saving
5
7
  # associated records when their parent is saved. In addition to saving, it
6
8
  # also destroys any associated records that were marked for destruction.
7
- # (See +mark_for_destruction+ and <tt>marked_for_destruction?</tt>).
9
+ # (See #mark_for_destruction and #marked_for_destruction?).
8
10
  #
9
11
  # Saving of the parent, its associations, and the destruction of marked
10
12
  # associations, all happen inside a transaction. This should never leave the
@@ -22,14 +24,14 @@ module ActiveRecord
22
24
  #
23
25
  # == Validation
24
26
  #
25
- # Children records are validated unless <tt>:validate</tt> is +false+.
27
+ # Child records are validated unless <tt>:validate</tt> is +false+.
26
28
  #
27
29
  # == Callbacks
28
30
  #
29
31
  # Association with autosave option defines several callbacks on your
30
- # model (before_save, after_create, after_update). Please note that
32
+ # model (around_save, before_save, after_create, after_update). Please note that
31
33
  # callbacks are executed in the order they were defined in
32
- # model. You should avoid modifying the association content, before
34
+ # model. You should avoid modifying the association content before
33
35
  # autosave callbacks are executed. Placing your callbacks after
34
36
  # associations is usually a good practice.
35
37
  #
@@ -89,8 +91,9 @@ module ActiveRecord
89
91
  # post.save # => saves both post and comment
90
92
  #
91
93
  # post = Post.create(title: 'ruby rocks')
92
- # post.comments.create(body: 'hello world')
93
- # 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
94
97
  #
95
98
  # When <tt>:autosave</tt> is true all children are saved, no matter whether they
96
99
  # are new records or not:
@@ -100,11 +103,10 @@ module ActiveRecord
100
103
  # end
101
104
  #
102
105
  # post = Post.create(title: 'ruby rocks')
103
- # post.comments.create(body: 'hello world')
104
- # post.comments[0].body = 'hi everyone'
106
+ # comment = post.comments.create(body: 'hello world')
107
+ # comment.body = 'hi everyone'
105
108
  # post.comments.build(body: "good morning.")
106
- # post.title += "!"
107
- # post.save # => saves both post and comments.
109
+ # post.save # => saves post and both comments.
108
110
  #
109
111
  # Destroying one of the associated models as part of the parent's save action
110
112
  # is as simple as marking it for destruction:
@@ -125,7 +127,14 @@ module ActiveRecord
125
127
  # Now it _is_ removed from the database:
126
128
  #
127
129
  # Comment.find_by(id: id).nil? # => true
128
-
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.
129
138
  module AutosaveAssociation
130
139
  extend ActiveSupport::Concern
131
140
 
@@ -141,22 +150,37 @@ module ActiveRecord
141
150
 
142
151
  included do
143
152
  Associations::Builder::Association.extensions << AssociationBuilderExtension
153
+ mattr_accessor :index_nested_attribute_errors, instance_writer: false, default: false
144
154
  end
145
155
 
146
- module ClassMethods
156
+ module ClassMethods # :nodoc:
147
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
148
171
 
149
172
  def define_non_cyclic_method(name, &block)
150
- return if method_defined?(name)
173
+ return if method_defined?(name, false)
174
+
151
175
  define_method(name) do |*args|
152
176
  result = true; @_already_called ||= {}
153
177
  # Loop prevention for validation of associations
154
178
  unless @_already_called[name]
155
179
  begin
156
- @_already_called[name]=true
180
+ @_already_called[name] = true
157
181
  result = instance_eval(&block)
158
182
  ensure
159
- @_already_called[name]=false
183
+ @_already_called[name] = false
160
184
  end
161
185
  end
162
186
 
@@ -177,11 +201,9 @@ module ActiveRecord
177
201
  # before actually defining them.
178
202
  def add_autosave_association_callbacks(reflection)
179
203
  save_method = :"autosave_associated_records_for_#{reflection.name}"
180
- validation_method = :"validate_associated_records_for_#{reflection.name}"
181
- collection = reflection.collection?
182
204
 
183
- if collection
184
- before_save :before_save_collection_association
205
+ if reflection.collection?
206
+ around_save :around_save_collection_association
185
207
 
186
208
  define_non_cyclic_method(save_method) { save_collection_association(reflection) }
187
209
  # Doesn't use after_save as that would save associations added in after_create/after_update twice
@@ -200,14 +222,25 @@ module ActiveRecord
200
222
  after_create save_method
201
223
  after_update save_method
202
224
  else
203
- define_non_cyclic_method(save_method) { save_belongs_to_association(reflection) }
225
+ define_non_cyclic_method(save_method) { throw(:abort) if save_belongs_to_association(reflection) == false }
204
226
  before_save save_method
205
227
  end
206
228
 
229
+ define_autosave_validation_callbacks(reflection)
230
+ end
231
+
232
+ def define_autosave_validation_callbacks(reflection)
233
+ validation_method = :"validate_associated_records_for_#{reflection.name}"
207
234
  if reflection.validate? && !method_defined?(validation_method)
208
- method = (collection ? :validate_collection_association : :validate_single_association)
235
+ if reflection.collection?
236
+ method = :validate_collection_association
237
+ else
238
+ method = :validate_single_association
239
+ end
240
+
209
241
  define_non_cyclic_method(validation_method) { send(method, reflection) }
210
242
  validate validation_method
243
+ after_validation :_ensure_no_duplicate_errors
211
244
  end
212
245
  end
213
246
  end
@@ -219,7 +252,7 @@ module ActiveRecord
219
252
  super
220
253
  end
221
254
 
222
- # Marks this record to be destroyed as part of the parents save transaction.
255
+ # Marks this record to be destroyed as part of the parent's save transaction.
223
256
  # This does _not_ actually destroy the record instantly, rather child record will be destroyed
224
257
  # when <tt>parent.save</tt> is called.
225
258
  #
@@ -228,7 +261,7 @@ module ActiveRecord
228
261
  @marked_for_destruction = true
229
262
  end
230
263
 
231
- # Returns whether or not this record will be destroyed as part of the parents save transaction.
264
+ # Returns whether or not this record will be destroyed as part of the parent's save transaction.
232
265
  #
233
266
  # Only useful if the <tt>:autosave</tt> option on the parent is enabled for this associated model.
234
267
  def marked_for_destruction?
@@ -251,32 +284,39 @@ module ActiveRecord
251
284
  # Returns whether or not this record has been changed in any way (including whether
252
285
  # any of its nested autosave associations are likewise changed)
253
286
  def changed_for_autosave?
254
- new_record? || changed? || marked_for_destruction? || nested_records_changed_for_autosave?
287
+ new_record? || has_changes_to_save? || marked_for_destruction? || nested_records_changed_for_autosave?
255
288
  end
256
289
 
257
290
  private
258
-
259
291
  # Returns the record for an association collection that should be validated
260
292
  # or saved. If +autosave+ is +false+ only new records will be returned,
261
293
  # unless the parent is/was a new record itself.
262
294
  def associated_records_to_validate_or_save(association, new_record, autosave)
263
- if new_record
295
+ if new_record || custom_validation_context?
264
296
  association && association.target
265
297
  elsif autosave
266
- association.target.find_all { |record| record.changed_for_autosave? }
298
+ association.target.find_all(&:changed_for_autosave?)
267
299
  else
268
- association.target.find_all { |record| record.new_record? }
300
+ association.target.find_all(&:new_record?)
269
301
  end
270
302
  end
271
303
 
272
- # go through nested autosave associations that are loaded in memory (without loading
273
- # 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.
274
307
  def nested_records_changed_for_autosave?
275
- self.class._reflections.values.any? do |reflection|
276
- if reflection.options[:autosave]
277
- association = association_instance_get(reflection.name)
278
- association && Array.wrap(association.target).any? { |a| a.changed_for_autosave? }
308
+ @_nested_records_changed_for_autosave_already_called ||= false
309
+ return false if @_nested_records_changed_for_autosave_already_called
310
+ begin
311
+ @_nested_records_changed_for_autosave_already_called = true
312
+ self.class._reflections.values.any? do |reflection|
313
+ if reflection.options[:autosave]
314
+ association = association_instance_get(reflection.name)
315
+ association && Array.wrap(association.target).any?(&:changed_for_autosave?)
316
+ end
279
317
  end
318
+ ensure
319
+ @_nested_records_changed_for_autosave_already_called = false
280
320
  end
281
321
  end
282
322
 
@@ -285,7 +325,7 @@ module ActiveRecord
285
325
  def validate_single_association(reflection)
286
326
  association = association_instance_get(reflection.name)
287
327
  record = association && association.reader
288
- association_valid?(reflection, record) if record
328
+ association_valid?(reflection, record) if record && (record.changed_for_autosave? || custom_validation_context?)
289
329
  end
290
330
 
291
331
  # Validate the associated records if <tt>:validate</tt> or
@@ -294,7 +334,7 @@ module ActiveRecord
294
334
  def validate_collection_association(reflection)
295
335
  if association = association_instance_get(reflection.name)
296
336
  if records = associated_records_to_validate_or_save(association, new_record?, reflection.options[:autosave])
297
- records.each { |record| association_valid?(reflection, record) }
337
+ records.each_with_index { |record, index| association_valid?(reflection, record, index) }
298
338
  end
299
339
  end
300
340
  end
@@ -302,17 +342,25 @@ module ActiveRecord
302
342
  # Returns whether or not the association is valid and applies any errors to
303
343
  # the parent, <tt>self</tt>, if it wasn't. Skips any <tt>:autosave</tt>
304
344
  # enabled records if they're marked_for_destruction? or destroyed.
305
- def association_valid?(reflection, record)
306
- return true if record.destroyed? || record.marked_for_destruction?
345
+ def association_valid?(reflection, record, index = nil)
346
+ return true if record.destroyed? || (reflection.options[:autosave] && record.marked_for_destruction?)
307
347
 
308
- validation_context = self.validation_context unless [:create, :update].include?(self.validation_context)
309
- unless valid = record.valid?(validation_context)
348
+ context = validation_context if custom_validation_context?
349
+
350
+ unless valid = record.valid?(context)
310
351
  if reflection.options[:autosave]
311
- record.errors.each do |attribute, message|
312
- attribute = "#{reflection.name}.#{attribute}"
313
- errors[attribute] << message
314
- errors[attribute].uniq!
315
- end
352
+ indexed_attribute = !index.nil? && (reflection.options[:index_errors] || ActiveRecord::Base.index_nested_attribute_errors)
353
+
354
+ record.errors.group_by_attribute.each { |attribute, errors|
355
+ attribute = normalize_reflection_attribute(indexed_attribute, reflection, index, attribute)
356
+
357
+ errors.each { |error|
358
+ self.errors.import(
359
+ error,
360
+ attribute: attribute
361
+ )
362
+ }
363
+ }
316
364
  else
317
365
  errors.add(reflection.name)
318
366
  end
@@ -320,18 +368,30 @@ module ActiveRecord
320
368
  valid
321
369
  end
322
370
 
323
- # Is used as a before_save callback to check while saving a collection
371
+ def normalize_reflection_attribute(indexed_attribute, reflection, index, attribute)
372
+ if indexed_attribute
373
+ "#{reflection.name}[#{index}].#{attribute}"
374
+ else
375
+ "#{reflection.name}.#{attribute}"
376
+ end
377
+ end
378
+
379
+ # Is used as an around_save callback to check while saving a collection
324
380
  # association whether or not the parent was a new record before saving.
325
- def before_save_collection_association
326
- @new_record_before_save = new_record?
327
- true
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?
384
+
385
+ yield
386
+ ensure
387
+ @new_record_before_save = previously_new_record_before_save
328
388
  end
329
389
 
330
390
  # Saves any new associated records, or all loaded autosave associations if
331
391
  # <tt>:autosave</tt> is enabled on the association.
332
392
  #
333
393
  # In addition, it destroys all children that were marked for destruction
334
- # with mark_for_destruction.
394
+ # with #mark_for_destruction.
335
395
  #
336
396
  # This all happens inside a transaction, _if_ the Transactions module is included into
337
397
  # ActiveRecord::Base after the AutosaveAssociation module, which it does by default.
@@ -339,7 +399,14 @@ module ActiveRecord
339
399
  if association = association_instance_get(reflection.name)
340
400
  autosave = reflection.options[:autosave]
341
401
 
342
- if records = associated_records_to_validate_or_save(association, @new_record_before_save, autosave)
402
+ # By saving the instance variable in a local variable,
403
+ # we make the whole callback re-entrant.
404
+ new_record_before_save = @new_record_before_save
405
+
406
+ # reconstruct the scope now that we know the owner's id
407
+ association.reset_scope
408
+
409
+ if records = associated_records_to_validate_or_save(association, new_record_before_save, autosave)
343
410
  if autosave
344
411
  records_to_destroy = records.select(&:marked_for_destruction?)
345
412
  records_to_destroy.each { |record| association.destroy(record) }
@@ -351,22 +418,24 @@ module ActiveRecord
351
418
 
352
419
  saved = true
353
420
 
354
- if autosave != false && (@new_record_before_save || record.new_record?)
421
+ if autosave != false && (new_record_before_save || record.new_record?)
355
422
  if autosave
356
423
  saved = association.insert_record(record, false)
357
- else
358
- association.insert_record(record) unless reflection.nested?
424
+ elsif !reflection.nested?
425
+ association_saved = association.insert_record(record)
426
+
427
+ if reflection.validate?
428
+ errors.add(reflection.name) unless association_saved
429
+ saved = association_saved
430
+ end
359
431
  end
360
432
  elsif autosave
361
- saved = record.save(:validate => false)
433
+ saved = record.save(validate: false)
362
434
  end
363
435
 
364
- raise ActiveRecord::Rollback unless saved
436
+ raise(RecordInvalid.new(association.owner)) unless saved
365
437
  end
366
438
  end
367
-
368
- # reconstruct the scope now that we know the owner's id
369
- association.reset_scope if association.respond_to?(:reset_scope)
370
439
  end
371
440
  end
372
441
 
@@ -374,7 +443,7 @@ module ActiveRecord
374
443
  # on the association.
375
444
  #
376
445
  # In addition, it will destroy the association if it was marked for
377
- # destruction with mark_for_destruction.
446
+ # destruction with #mark_for_destruction.
378
447
  #
379
448
  # This all happens inside a transaction, _if_ the Transactions module is included into
380
449
  # ActiveRecord::Base after the AutosaveAssociation module, which it does by default.
@@ -388,14 +457,17 @@ module ActiveRecord
388
457
  if autosave && record.marked_for_destruction?
389
458
  record.destroy
390
459
  elsif autosave != false
391
- key = reflection.options[:primary_key] ? send(reflection.options[:primary_key]) : id
460
+ key = reflection.options[:primary_key] ? public_send(reflection.options[:primary_key]) : id
392
461
 
393
- 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)
394
463
  unless reflection.through_reflection
395
464
  record[reflection.foreign_key] = key
465
+ if inverse_reflection = reflection.inverse_of
466
+ record.association(inverse_reflection.name).inversed_from(self)
467
+ end
396
468
  end
397
469
 
398
- saved = record.save(:validate => !autosave)
470
+ saved = record.save(validate: !autosave)
399
471
  raise ActiveRecord::Rollback if !saved && autosave
400
472
  saved
401
473
  end
@@ -406,8 +478,14 @@ module ActiveRecord
406
478
  # If the record is new or it has changed, returns true.
407
479
  def record_changed?(reflection, record, key)
408
480
  record.new_record? ||
409
- (record.has_attribute?(reflection.foreign_key) && record[reflection.foreign_key] != key) ||
410
- record.attribute_changed?(reflection.foreign_key)
481
+ association_foreign_key_changed?(reflection, record, key) ||
482
+ record.will_save_change_to_attribute?(reflection.foreign_key)
483
+ end
484
+
485
+ def association_foreign_key_changed?(reflection, record, key)
486
+ return false if reflection.through_reflection?
487
+
488
+ record._has_attribute?(reflection.foreign_key) && record._read_attribute(reflection.foreign_key) != key
411
489
  end
412
490
 
413
491
  # Saves the associated record if it's new or <tt>:autosave</tt> is enabled.
@@ -415,7 +493,9 @@ module ActiveRecord
415
493
  # In addition, it will destroy the association if it was marked for destruction.
416
494
  def save_belongs_to_association(reflection)
417
495
  association = association_instance_get(reflection.name)
418
- record = association && association.load_target
496
+ return unless association && association.loaded? && !association.stale_target?
497
+
498
+ record = association.load_target
419
499
  if record && !record.destroyed?
420
500
  autosave = reflection.options[:autosave]
421
501
 
@@ -423,10 +503,10 @@ module ActiveRecord
423
503
  self[reflection.foreign_key] = nil
424
504
  record.destroy
425
505
  elsif autosave != false
426
- saved = record.save(:validate => !autosave) if record.new_record? || (autosave && record.changed_for_autosave?)
506
+ saved = record.save(validate: !autosave) if record.new_record? || (autosave && record.changed_for_autosave?)
427
507
 
428
508
  if association.updated?
429
- association_id = record.send(reflection.options[:primary_key] || :id)
509
+ association_id = record.public_send(reflection.options[:primary_key] || :id)
430
510
  self[reflection.foreign_key] = association_id
431
511
  association.loaded!
432
512
  end
@@ -435,5 +515,13 @@ module ActiveRecord
435
515
  end
436
516
  end
437
517
  end
518
+
519
+ def custom_validation_context?
520
+ validation_context && [:create, :update].exclude?(validation_context)
521
+ end
522
+
523
+ def _ensure_no_duplicate_errors
524
+ errors.uniq!
525
+ end
438
526
  end
439
527
  end
@@ -1,27 +1,16 @@
1
- require 'yaml'
2
- require 'set'
3
- require 'active_support/benchmarkable'
4
- require 'active_support/dependencies'
5
- require 'active_support/descendants_tracker'
6
- require 'active_support/time'
7
- require 'active_support/core_ext/module/attribute_accessors'
8
- require 'active_support/core_ext/class/delegating_attributes'
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
- require 'active_support/core_ext/class/subclasses'
18
- require 'arel'
19
- require 'active_record/attribute_decorators'
20
- require 'active_record/errors'
21
- require 'active_record/log_subscriber'
22
- require 'active_record/explain_subscriber'
23
- require 'active_record/relation/delegation'
24
- require 'active_record/attributes'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/benchmarkable"
4
+ require "active_support/dependencies"
5
+ require "active_support/descendants_tracker"
6
+ require "active_support/time"
7
+ require "active_support/core_ext/class/subclasses"
8
+ require "active_record/log_subscriber"
9
+ require "active_record/explain_subscriber"
10
+ require "active_record/relation/delegation"
11
+ require "active_record/attributes"
12
+ require "active_record/type_caster"
13
+ require "active_record/database_configurations"
25
14
 
26
15
  module ActiveRecord #:nodoc:
27
16
  # = Active Record
@@ -119,29 +108,25 @@ module ActiveRecord #:nodoc:
119
108
  # All column values are automatically available through basic accessors on the Active Record
120
109
  # object, but sometimes you want to specialize this behavior. This can be done by overwriting
121
110
  # the default accessors (using the same name as the attribute) and calling
122
- # <tt>read_attribute(attr_name)</tt> and <tt>write_attribute(attr_name, value)</tt> to actually
123
- # change things.
111
+ # +super+ to actually change things.
124
112
  #
125
113
  # class Song < ActiveRecord::Base
126
114
  # # Uses an integer of seconds to hold the length of the song
127
115
  #
128
116
  # def length=(minutes)
129
- # write_attribute(:length, minutes.to_i * 60)
117
+ # super(minutes.to_i * 60)
130
118
  # end
131
119
  #
132
120
  # def length
133
- # read_attribute(:length) / 60
121
+ # super / 60
134
122
  # end
135
123
  # end
136
124
  #
137
- # You can alternatively use <tt>self[:attribute]=(value)</tt> and <tt>self[:attribute]</tt>
138
- # instead of <tt>write_attribute(:attribute, value)</tt> and <tt>read_attribute(:attribute)</tt>.
139
- #
140
125
  # == Attribute query methods
141
126
  #
142
127
  # In addition to the basic accessors, query methods are also automatically available on the Active Record object.
143
128
  # Query methods allow you to test whether an attribute value is present.
144
- # For numeric values, present is defined as non-zero.
129
+ # Additionally, when dealing with numeric values, a query method will return false if the value is zero.
145
130
  #
146
131
  # For example, an Active Record User with the <tt>name</tt> attribute has a <tt>name?</tt> method that you can call
147
132
  # to determine whether the user has a name:
@@ -172,10 +157,11 @@ module ActiveRecord #:nodoc:
172
157
  # <tt>Person.find_by_user_name(user_name)</tt>.
173
158
  #
174
159
  # It's possible to add an exclamation point (!) on the end of the dynamic finders to get them to raise an
175
- # <tt>ActiveRecord::RecordNotFound</tt> error if they do not return any records,
160
+ # ActiveRecord::RecordNotFound error if they do not return any records,
176
161
  # like <tt>Person.find_by_last_name!</tt>.
177
162
  #
178
- # It's also possible to use multiple attributes in the same find by separating them with "_and_".
163
+ # It's also possible to use multiple attributes in the same <tt>find_by_</tt> by separating them with
164
+ # "_and_".
179
165
  #
180
166
  # Person.find_by(user_name: user_name, password: password)
181
167
  # Person.find_by_user_name_and_password(user_name, password) # with dynamic finder
@@ -187,7 +173,8 @@ module ActiveRecord #:nodoc:
187
173
  # == Saving arrays, hashes, and other non-mappable objects in text columns
188
174
  #
189
175
  # Active Record can serialize any object in text columns using YAML. To do so, you must
190
- # specify this with a call to the class method +serialize+.
176
+ # specify this with a call to the class method
177
+ # {serialize}[rdoc-ref:AttributeMethods::Serialization::ClassMethods#serialize].
191
178
  # This makes it possible to store arrays, hashes, and other non-mappable objects without doing
192
179
  # any additional work.
193
180
  #
@@ -227,39 +214,47 @@ module ActiveRecord #:nodoc:
227
214
  #
228
215
  # == Connection to multiple databases in different models
229
216
  #
230
- # Connections are usually created through ActiveRecord::Base.establish_connection and retrieved
217
+ # Connections are usually created through
218
+ # {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection] and retrieved
231
219
  # by ActiveRecord::Base.connection. All classes inheriting from ActiveRecord::Base will use this
232
220
  # connection. But you can also set a class-specific connection. For example, if Course is an
233
221
  # ActiveRecord::Base, but resides in a different database, you can just say <tt>Course.establish_connection</tt>
234
222
  # and Course and all of its subclasses will use this connection instead.
235
223
  #
236
224
  # 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 retrieve_connection method
225
+ # a hash indexed by the class. If a connection is requested, the
226
+ # {ActiveRecord::Base.retrieve_connection}[rdoc-ref:ConnectionHandling#retrieve_connection] method
238
227
  # will go up the class-hierarchy until a connection is found in the connection pool.
239
228
  #
240
229
  # == Exceptions
241
230
  #
242
231
  # * ActiveRecordError - Generic error class and superclass of all other errors raised by Active Record.
243
- # * AdapterNotSpecified - The configuration hash used in <tt>establish_connection</tt> didn't include an
244
- # <tt>:adapter</tt> key.
245
- # * AdapterNotFound - The <tt>:adapter</tt> key used in <tt>establish_connection</tt> specified a
246
- # non-existent adapter
232
+ # * AdapterNotSpecified - The configuration hash used in
233
+ # {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection]
234
+ # didn't include an <tt>:adapter</tt> key.
235
+ # * AdapterNotFound - The <tt>:adapter</tt> key used in
236
+ # {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection]
237
+ # specified a non-existent adapter
247
238
  # (or a bad spelling of an existing one).
248
239
  # * AssociationTypeMismatch - The object assigned to the association wasn't of the type
249
240
  # specified in the association definition.
250
241
  # * AttributeAssignmentError - An error occurred while doing a mass assignment through the
251
- # <tt>attributes=</tt> method.
242
+ # {ActiveRecord::Base#attributes=}[rdoc-ref:AttributeAssignment#attributes=] method.
252
243
  # You can inspect the +attribute+ property of the exception object to determine which attribute
253
244
  # triggered the error.
254
- # * ConnectionNotEstablished - No connection has been established. Use <tt>establish_connection</tt>
255
- # before querying.
245
+ # * ConnectionNotEstablished - No connection has been established.
246
+ # Use {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection] before querying.
256
247
  # * MultiparameterAssignmentErrors - Collection of errors that occurred during a mass assignment using the
257
- # <tt>attributes=</tt> method. The +errors+ property of this exception contains an array of
248
+ # {ActiveRecord::Base#attributes=}[rdoc-ref:AttributeAssignment#attributes=] method.
249
+ # The +errors+ property of this exception contains an array of
258
250
  # AttributeAssignmentError
259
251
  # objects that should be inspected to determine which attributes triggered the errors.
260
- # * RecordInvalid - raised by save! and create! when the record is invalid.
261
- # * RecordNotFound - No record responded to the +find+ method. Either the row with the given ID doesn't exist
262
- # or the row didn't meet the additional restrictions. Some +find+ calls do not raise this exception to signal
252
+ # * RecordInvalid - raised by {ActiveRecord::Base#save!}[rdoc-ref:Persistence#save!] and
253
+ # {ActiveRecord::Base.create!}[rdoc-ref:Persistence::ClassMethods#create!]
254
+ # when the record is invalid.
255
+ # * RecordNotFound - No record responded to the {ActiveRecord::Base.find}[rdoc-ref:FinderMethods#find] method.
256
+ # Either the row with the given ID doesn't exist or the row didn't meet the additional restrictions.
257
+ # Some {ActiveRecord::Base.find}[rdoc-ref:FinderMethods#find] calls do not raise this exception to signal
263
258
  # nothing was found, please check its documentation for further details.
264
259
  # * SerializationTypeMismatch - The serialized object wasn't of the class specified as the second parameter.
265
260
  # * StatementInvalid - The database server rejected the SQL statement. The precise error is added in the message.
@@ -278,9 +273,11 @@ module ActiveRecord #:nodoc:
278
273
  extend Querying
279
274
  extend Translation
280
275
  extend DynamicMatchers
276
+ extend DelegatedType
281
277
  extend Explain
282
278
  extend Enum
283
279
  extend Delegation::DelegateCache
280
+ extend Aggregations::ClassMethods
284
281
 
285
282
  include Core
286
283
  include Persistence
@@ -295,7 +292,6 @@ module ActiveRecord #:nodoc:
295
292
  include Validations
296
293
  include CounterCache
297
294
  include Attributes
298
- include AttributeDecorators
299
295
  include Locking::Optimistic
300
296
  include Locking::Pessimistic
301
297
  include AttributeMethods
@@ -305,12 +301,15 @@ module ActiveRecord #:nodoc:
305
301
  include ActiveModel::SecurePassword
306
302
  include AutosaveAssociation
307
303
  include NestedAttributes
308
- include Aggregations
309
304
  include Transactions
305
+ include TouchLater
310
306
  include NoTouching
311
307
  include Reflection
312
308
  include Serialization
313
309
  include Store
310
+ include SecureToken
311
+ include SignedId
312
+ include Suppressor
314
313
  end
315
314
 
316
315
  ActiveSupport.run_load_hooks(:active_record, Base)