activerecord 4.2.9 → 6.1.4.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 (374) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +964 -1382
  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 +266 -251
  8. data/lib/active_record/association_relation.rb +40 -15
  9. data/lib/active_record/associations/alias_tracker.rb +40 -43
  10. data/lib/active_record/associations/association.rb +162 -69
  11. data/lib/active_record/associations/association_scope.rb +105 -130
  12. data/lib/active_record/associations/belongs_to_association.rb +83 -65
  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 -37
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +49 -66
  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 +148 -287
  22. data/lib/active_record/associations/collection_proxy.rb +252 -150
  23. data/lib/active_record/associations/foreign_association.rb +23 -1
  24. data/lib/active_record/associations/has_many_association.rb +56 -98
  25. data/lib/active_record/associations/has_many_through_association.rb +68 -89
  26. data/lib/active_record/associations/has_one_association.rb +73 -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 -81
  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 +174 -169
  32. data/lib/active_record/associations/preloader/association.rb +108 -115
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  34. data/lib/active_record/associations/preloader.rb +97 -94
  35. data/lib/active_record/associations/singular_association.rb +18 -39
  36. data/lib/active_record/associations/through_association.rb +39 -19
  37. data/lib/active_record/associations.rb +1845 -1598
  38. data/lib/active_record/attribute_assignment.rb +59 -185
  39. data/lib/active_record/attribute_methods/before_type_cast.rb +18 -10
  40. data/lib/active_record/attribute_methods/dirty.rb +168 -148
  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 +55 -36
  46. data/lib/active_record/attribute_methods/write.rb +24 -55
  47. data/lib/active_record/attribute_methods.rb +149 -154
  48. data/lib/active_record/attributes.rb +234 -78
  49. data/lib/active_record/autosave_association.rb +133 -60
  50. data/lib/active_record/base.rb +46 -46
  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 +34 -13
  54. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -323
  55. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
  56. data/lib/active_record/connection_adapters/abstract/database_statements.rb +292 -124
  57. data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
  58. data/lib/active_record/connection_adapters/abstract/quoting.rb +177 -60
  59. data/lib/active_record/connection_adapters/abstract/savepoints.rb +8 -6
  60. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
  61. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +473 -255
  62. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  63. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +869 -286
  64. data/lib/active_record/connection_adapters/abstract/transaction.rb +257 -91
  65. data/lib/active_record/connection_adapters/abstract_adapter.rb +483 -230
  66. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +557 -640
  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 +194 -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 +268 -0
  78. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
  79. data/lib/active_record/connection_adapters/mysql2_adapter.rb +80 -192
  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 +75 -160
  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 -58
  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 +4 -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 +14 -19
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
  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 -5
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  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 +145 -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 +496 -298
  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 +588 -375
  119. data/lib/active_record/connection_adapters/schema_cache.rb +167 -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 +144 -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 -373
  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 +458 -241
  133. data/lib/active_record/counter_cache.rb +70 -49
  134. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -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 +272 -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 +211 -92
  143. data/lib/active_record/errors.rb +224 -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 +10 -5
  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 +275 -500
  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 +62 -0
  158. data/lib/active_record/legacy_yaml_adapter.rb +27 -5
  159. data/lib/active_record/locale/en.yml +3 -2
  160. data/lib/active_record/locking/optimistic.rb +98 -92
  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 +295 -0
  168. data/lib/active_record/migration/join_table.rb +8 -7
  169. data/lib/active_record/migration.rb +673 -325
  170. data/lib/active_record/model_schema.rb +418 -113
  171. data/lib/active_record/nested_attributes.rb +263 -224
  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 +572 -136
  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 +170 -51
  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 +523 -199
  181. data/lib/active_record/readonly_attributes.rb +9 -4
  182. data/lib/active_record/reflection.rb +454 -291
  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 +324 -249
  186. data/lib/active_record/relation/delegation.rb +76 -84
  187. data/lib/active_record/relation/finder_methods.rb +316 -242
  188. data/lib/active_record/relation/from_clause.rb +30 -0
  189. data/lib/active_record/relation/merger.rb +95 -103
  190. data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -26
  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 +136 -122
  197. data/lib/active_record/relation/query_attribute.rb +50 -0
  198. data/lib/active_record/relation/query_methods.rb +757 -413
  199. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  200. data/lib/active_record/relation/spawn_methods.rb +18 -20
  201. data/lib/active_record/relation/where_clause.rb +239 -0
  202. data/lib/active_record/relation.rb +554 -343
  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 -23
  209. data/lib/active_record/scoping/default.rb +96 -83
  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 +128 -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 +364 -130
  220. data/lib/active_record/tasks/mysql_database_tasks.rb +67 -113
  221. data/lib/active_record/tasks/postgresql_database_tasks.rb +86 -49
  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 +287 -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 +182 -163
  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 -45
  231. data/lib/active_record/type/date_time.rb +4 -49
  232. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  233. data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
  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 +27 -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 +63 -56
  251. data/lib/active_record/validations.rb +39 -35
  252. data/lib/active_record/version.rb +3 -1
  253. data/lib/active_record.rb +42 -29
  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 -4
  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/model/templates/{module.rb → module.rb.tt} +0 -0
  339. data/lib/rails/generators/active_record.rb +7 -5
  340. metadata +172 -65
  341. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  342. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  343. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  344. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  345. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  346. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  347. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  348. data/lib/active_record/attribute.rb +0 -163
  349. data/lib/active_record/attribute_decorators.rb +0 -66
  350. data/lib/active_record/attribute_set/builder.rb +0 -106
  351. data/lib/active_record/attribute_set.rb +0 -81
  352. data/lib/active_record/connection_adapters/connection_specification.rb +0 -275
  353. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  354. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  355. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  356. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  357. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  358. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  359. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  360. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  361. data/lib/active_record/type/big_integer.rb +0 -13
  362. data/lib/active_record/type/binary.rb +0 -50
  363. data/lib/active_record/type/boolean.rb +0 -31
  364. data/lib/active_record/type/decimal.rb +0 -64
  365. data/lib/active_record/type/decorator.rb +0 -14
  366. data/lib/active_record/type/float.rb +0 -19
  367. data/lib/active_record/type/integer.rb +0 -59
  368. data/lib/active_record/type/mutable.rb +0 -16
  369. data/lib/active_record/type/numeric.rb +0 -36
  370. data/lib/active_record/type/string.rb +0 -40
  371. data/lib/active_record/type/time_value.rb +0 -38
  372. data/lib/active_record/type/value.rb +0 -110
  373. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -19
  374. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
@@ -1,10 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Associations
3
- # Association proxies in Active Record are middlemen between the object that
4
- # holds the association, known as the <tt>@owner</tt>, and the actual associated
5
- # object, known as the <tt>@target</tt>. The kind of association any proxy is
6
- # about is available in <tt>@reflection</tt>. That's an instance of the class
7
- # ActiveRecord::Reflection::AssociationReflection.
5
+ # Collection proxies in Active Record are middlemen between an
6
+ # <tt>association</tt>, and its <tt>target</tt> result set.
8
7
  #
9
8
  # For example, given
10
9
  #
@@ -14,27 +13,26 @@ module ActiveRecord
14
13
  #
15
14
  # blog = Blog.first
16
15
  #
17
- # the association proxy in <tt>blog.posts</tt> has the object in +blog+ as
18
- # <tt>@owner</tt>, the collection of its posts as <tt>@target</tt>, and
19
- # the <tt>@reflection</tt> object represents a <tt>:has_many</tt> macro.
16
+ # The collection proxy returned by <tt>blog.posts</tt> is built from a
17
+ # <tt>:has_many</tt> <tt>association</tt>, and delegates to a collection
18
+ # of posts as the <tt>target</tt>.
20
19
  #
21
- # This class delegates unknown methods to <tt>@target</tt> via
22
- # <tt>method_missing</tt>.
20
+ # This class delegates unknown methods to the <tt>association</tt>'s
21
+ # relation class via a delegate cache.
23
22
  #
24
- # The <tt>@target</tt> object is not \loaded until needed. For example,
23
+ # The <tt>target</tt> result set is not loaded until needed. For example,
25
24
  #
26
25
  # blog.posts.count
27
26
  #
28
27
  # is computed directly through SQL and does not trigger by itself the
29
28
  # instantiation of the actual post records.
30
29
  class CollectionProxy < Relation
31
- delegate(*(ActiveRecord::Calculations.public_instance_methods - [:count]), to: :scope)
32
- delegate :find_nth, to: :scope
33
-
34
- def initialize(klass, association) #:nodoc:
30
+ def initialize(klass, association, **) #:nodoc:
35
31
  @association = association
36
- super klass, klass.arel_table
37
- merge! association.scope(nullify: false)
32
+ super klass
33
+
34
+ extensions = association.extensions
35
+ extend(*extensions) if extensions.any?
38
36
  end
39
37
 
40
38
  def target
@@ -53,7 +51,14 @@ module ActiveRecord
53
51
  def loaded?
54
52
  @association.loaded?
55
53
  end
54
+ alias :loaded :loaded?
56
55
 
56
+ ##
57
+ # :method: select
58
+ #
59
+ # :call-seq:
60
+ # select(*fields, &block)
61
+ #
57
62
  # Works in two ways.
58
63
  #
59
64
  # *First:* Specify a subset of fields to be selected from the result set.
@@ -76,7 +81,7 @@ module ActiveRecord
76
81
  # # #<Pet id: nil, name: "Choo-Choo">
77
82
  # # ]
78
83
  #
79
- # person.pets.select(:id, :name )
84
+ # person.pets.select(:id, :name)
80
85
  # # => [
81
86
  # # #<Pet id: 1, name: "Fancy-Fancy">,
82
87
  # # #<Pet id: 2, name: "Spook">,
@@ -96,23 +101,14 @@ module ActiveRecord
96
101
  # converting them into an array and iterating through them using
97
102
  # Array#select.
98
103
  #
99
- # person.pets.select { |pet| pet.name =~ /oo/ }
104
+ # person.pets.select { |pet| /oo/.match?(pet.name) }
100
105
  # # => [
101
106
  # # #<Pet id: 2, name: "Spook", person_id: 1>,
102
107
  # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
103
108
  # # ]
104
- #
105
- # person.pets.select(:name) { |pet| pet.name =~ /oo/ }
106
- # # => [
107
- # # #<Pet id: 2, name: "Spook">,
108
- # # #<Pet id: 3, name: "Choo-Choo">
109
- # # ]
110
- def select(*fields, &block)
111
- @association.select(*fields, &block)
112
- end
113
109
 
114
110
  # Finds an object in the collection responding to the +id+. Uses the same
115
- # rules as <tt>ActiveRecord::Base.find</tt>. Returns <tt>ActiveRecord::RecordNotFound</tt>
111
+ # rules as ActiveRecord::Base.find. Returns ActiveRecord::RecordNotFound
116
112
  # error if the object cannot be found.
117
113
  #
118
114
  # class Person < ActiveRecord::Base
@@ -127,7 +123,7 @@ module ActiveRecord
127
123
  # # ]
128
124
  #
129
125
  # person.pets.find(1) # => #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>
130
- # person.pets.find(4) # => ActiveRecord::RecordNotFound: Couldn't find Pet with id=4
126
+ # person.pets.find(4) # => ActiveRecord::RecordNotFound: Couldn't find Pet with 'id'=4
131
127
  #
132
128
  # person.pets.find(2) { |pet| pet.name.downcase! }
133
129
  # # => #<Pet id: 2, name: "fancy-fancy", person_id: 1>
@@ -137,10 +133,17 @@ module ActiveRecord
137
133
  # # #<Pet id: 2, name: "Spook", person_id: 1>,
138
134
  # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
139
135
  # # ]
140
- def find(*args, &block)
141
- @association.find(*args, &block)
136
+ def find(*args)
137
+ return super if block_given?
138
+ @association.find(*args)
142
139
  end
143
140
 
141
+ ##
142
+ # :method: first
143
+ #
144
+ # :call-seq:
145
+ # first(limit = nil)
146
+ #
144
147
  # Returns the first record, or the first +n+ records, from the collection.
145
148
  # If the collection is empty, the first form returns +nil+, and the second
146
149
  # form returns an empty array.
@@ -167,35 +170,63 @@ module ActiveRecord
167
170
  # another_person_without.pets # => []
168
171
  # another_person_without.pets.first # => nil
169
172
  # another_person_without.pets.first(3) # => []
170
- def first(*args)
171
- @association.first(*args)
172
- end
173
173
 
174
- # Same as +first+ except returns only the second record.
175
- def second(*args)
176
- @association.second(*args)
177
- end
174
+ ##
175
+ # :method: second
176
+ #
177
+ # :call-seq:
178
+ # second()
179
+ #
180
+ # Same as #first except returns only the second record.
178
181
 
179
- # Same as +first+ except returns only the third record.
180
- def third(*args)
181
- @association.third(*args)
182
- end
182
+ ##
183
+ # :method: third
184
+ #
185
+ # :call-seq:
186
+ # third()
187
+ #
188
+ # Same as #first except returns only the third record.
183
189
 
184
- # Same as +first+ except returns only the fourth record.
185
- def fourth(*args)
186
- @association.fourth(*args)
187
- end
190
+ ##
191
+ # :method: fourth
192
+ #
193
+ # :call-seq:
194
+ # fourth()
195
+ #
196
+ # Same as #first except returns only the fourth record.
188
197
 
189
- # Same as +first+ except returns only the fifth record.
190
- def fifth(*args)
191
- @association.fifth(*args)
192
- end
198
+ ##
199
+ # :method: fifth
200
+ #
201
+ # :call-seq:
202
+ # fifth()
203
+ #
204
+ # Same as #first except returns only the fifth record.
193
205
 
194
- # Same as +first+ except returns only the forty second record.
206
+ ##
207
+ # :method: forty_two
208
+ #
209
+ # :call-seq:
210
+ # forty_two()
211
+ #
212
+ # Same as #first except returns only the forty second record.
195
213
  # Also known as accessing "the reddit".
196
- def forty_two(*args)
197
- @association.forty_two(*args)
198
- end
214
+
215
+ ##
216
+ # :method: third_to_last
217
+ #
218
+ # :call-seq:
219
+ # third_to_last()
220
+ #
221
+ # Same as #first except returns only the third-to-last record.
222
+
223
+ ##
224
+ # :method: second_to_last
225
+ #
226
+ # :call-seq:
227
+ # second_to_last()
228
+ #
229
+ # Same as #first except returns only the second-to-last record.
199
230
 
200
231
  # Returns the last record, or the last +n+ records, from the collection.
201
232
  # If the collection is empty, the first form returns +nil+, and the second
@@ -223,12 +254,39 @@ module ActiveRecord
223
254
  # another_person_without.pets # => []
224
255
  # another_person_without.pets.last # => nil
225
256
  # another_person_without.pets.last(3) # => []
226
- def last(*args)
227
- @association.last(*args)
257
+ def last(limit = nil)
258
+ load_target if find_from_target?
259
+ super
228
260
  end
229
261
 
230
- def take(n = nil)
231
- @association.take(n)
262
+ # Gives a record (or N records if a parameter is supplied) from the collection
263
+ # using the same rules as <tt>ActiveRecord::Base.take</tt>.
264
+ #
265
+ # class Person < ActiveRecord::Base
266
+ # has_many :pets
267
+ # end
268
+ #
269
+ # person.pets
270
+ # # => [
271
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
272
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
273
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
274
+ # # ]
275
+ #
276
+ # person.pets.take # => #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>
277
+ #
278
+ # person.pets.take(2)
279
+ # # => [
280
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
281
+ # # #<Pet id: 2, name: "Spook", person_id: 1>
282
+ # # ]
283
+ #
284
+ # another_person_without.pets # => []
285
+ # another_person_without.pets.take # => nil
286
+ # another_person_without.pets.take(2) # => []
287
+ def take(limit = nil)
288
+ load_target if find_from_target?
289
+ super
232
290
  end
233
291
 
234
292
  # Returns a new object of the collection type that has been instantiated
@@ -290,7 +348,7 @@ module ActiveRecord
290
348
  @association.create(attributes, &block)
291
349
  end
292
350
 
293
- # Like +create+, except that if the record is invalid, raises an exception.
351
+ # Like #create, except that if the record is invalid, raises an exception.
294
352
  #
295
353
  # class Person
296
354
  # has_many :pets
@@ -306,34 +364,6 @@ module ActiveRecord
306
364
  @association.create!(attributes, &block)
307
365
  end
308
366
 
309
- # Add one or more records to the collection by setting their foreign keys
310
- # to the association's primary key. Since << flattens its argument list and
311
- # inserts each record, +push+ and +concat+ behave identically. Returns +self+
312
- # so method calls may be chained.
313
- #
314
- # class Person < ActiveRecord::Base
315
- # has_many :pets
316
- # end
317
- #
318
- # person.pets.size # => 0
319
- # person.pets.concat(Pet.new(name: 'Fancy-Fancy'))
320
- # person.pets.concat(Pet.new(name: 'Spook'), Pet.new(name: 'Choo-Choo'))
321
- # person.pets.size # => 3
322
- #
323
- # person.id # => 1
324
- # person.pets
325
- # # => [
326
- # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
327
- # # #<Pet id: 2, name: "Spook", person_id: 1>,
328
- # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
329
- # # ]
330
- #
331
- # person.pets.concat([Pet.new(name: 'Brain'), Pet.new(name: 'Benny')])
332
- # person.pets.size # => 5
333
- def concat(*records)
334
- @association.concat(*records)
335
- end
336
-
337
367
  # Replaces this collection with +other_array+. This will perform a diff
338
368
  # and delete/add only records that have changed.
339
369
  #
@@ -344,7 +374,7 @@ module ActiveRecord
344
374
  # person.pets
345
375
  # # => [#<Pet id: 1, name: "Gorby", group: "cats", person_id: 1>]
346
376
  #
347
- # other_pets = [Pet.new(name: 'Puff', group: 'celebrities']
377
+ # other_pets = [Pet.new(name: 'Puff', group: 'celebrities')]
348
378
  #
349
379
  # person.pets.replace(other_pets)
350
380
  #
@@ -364,7 +394,7 @@ module ActiveRecord
364
394
  # specified by the +:dependent+ option. If no +:dependent+ option is given,
365
395
  # then it will follow the default strategy.
366
396
  #
367
- # For +has_many :through+ associations, the default deletion strategy is
397
+ # For <tt>has_many :through</tt> associations, the default deletion strategy is
368
398
  # +:delete_all+.
369
399
  #
370
400
  # For +has_many+ associations, the default deletion strategy is +:nullify+.
@@ -399,7 +429,7 @@ module ActiveRecord
399
429
  # # #<Pet id: 3, name: "Choo-Choo", person_id: nil>
400
430
  # # ]
401
431
  #
402
- # Both +has_many+ and +has_many :through+ dependencies default to the
432
+ # Both +has_many+ and <tt>has_many :through</tt> dependencies default to the
403
433
  # +:delete_all+ strategy if the +:dependent+ option is set to +:destroy+.
404
434
  # Records are not instantiated and callbacks will not be fired.
405
435
  #
@@ -418,7 +448,7 @@ module ActiveRecord
418
448
  # person.pets.delete_all
419
449
  #
420
450
  # Pet.find(1, 2, 3)
421
- # # => ActiveRecord::RecordNotFound
451
+ # # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
422
452
  #
423
453
  # If it is set to <tt>:delete_all</tt>, all the objects are deleted
424
454
  # *without* calling their +destroy+ method.
@@ -438,9 +468,9 @@ module ActiveRecord
438
468
  # person.pets.delete_all
439
469
  #
440
470
  # Pet.find(1, 2, 3)
441
- # # => ActiveRecord::RecordNotFound
471
+ # # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
442
472
  def delete_all(dependent = nil)
443
- @association.delete_all(dependent)
473
+ @association.delete_all(dependent).tap { reset_scope }
444
474
  end
445
475
 
446
476
  # Deletes the records of the collection directly from the database
@@ -467,7 +497,7 @@ module ActiveRecord
467
497
  #
468
498
  # Pet.find(1) # => Couldn't find Pet with id=1
469
499
  def destroy_all
470
- @association.destroy_all
500
+ @association.destroy_all.tap { reset_scope }
471
501
  end
472
502
 
473
503
  # Deletes the +records+ supplied from the collection according to the strategy
@@ -475,7 +505,7 @@ module ActiveRecord
475
505
  # then it will follow the default strategy. Returns an array with the
476
506
  # deleted records.
477
507
  #
478
- # For +has_many :through+ associations, the default deletion strategy is
508
+ # For <tt>has_many :through</tt> associations, the default deletion strategy is
479
509
  # +:delete_all+.
480
510
  #
481
511
  # For +has_many+ associations, the default deletion strategy is +:nullify+.
@@ -532,7 +562,7 @@ module ActiveRecord
532
562
  # # => [#<Pet id: 2, name: "Spook", person_id: 1>]
533
563
  #
534
564
  # Pet.find(1, 3)
535
- # # => ActiveRecord::RecordNotFound: Couldn't find all Pets with IDs (1, 3)
565
+ # # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 3)
536
566
  #
537
567
  # If it is set to <tt>:delete_all</tt>, all the +records+ are deleted
538
568
  # *without* calling their +destroy+ method.
@@ -560,7 +590,7 @@ module ActiveRecord
560
590
  # # ]
561
591
  #
562
592
  # Pet.find(1)
563
- # # => ActiveRecord::RecordNotFound: Couldn't find Pet with id=1
593
+ # # => ActiveRecord::RecordNotFound: Couldn't find Pet with 'id'=1
564
594
  #
565
595
  # You can pass +Integer+ or +String+ values, it finds the records
566
596
  # responding to the +id+ and executes delete on them.
@@ -586,7 +616,7 @@ module ActiveRecord
586
616
  # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
587
617
  # # ]
588
618
  def delete(*records)
589
- @association.delete(*records)
619
+ @association.delete(*records).tap { reset_scope }
590
620
  end
591
621
 
592
622
  # Destroys the +records+ supplied and removes them from the collection.
@@ -624,7 +654,7 @@ module ActiveRecord
624
654
  # person.pets.size # => 0
625
655
  # person.pets # => []
626
656
  #
627
- # Pet.find(1, 2, 3) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with IDs (1, 2, 3)
657
+ # Pet.find(1, 2, 3) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
628
658
  #
629
659
  # You can pass +Integer+ or +String+ values, it finds the records
630
660
  # responding to the +id+ and then deletes them from the database.
@@ -656,11 +686,17 @@ module ActiveRecord
656
686
  # person.pets.size # => 0
657
687
  # person.pets # => []
658
688
  #
659
- # Pet.find(4, 5, 6) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with IDs (4, 5, 6)
689
+ # Pet.find(4, 5, 6) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (4, 5, 6)
660
690
  def destroy(*records)
661
- @association.destroy(*records)
691
+ @association.destroy(*records).tap { reset_scope }
662
692
  end
663
693
 
694
+ ##
695
+ # :method: distinct
696
+ #
697
+ # :call-seq:
698
+ # distinct(value = true)
699
+ #
664
700
  # Specifies whether the records should be unique or not.
665
701
  #
666
702
  # class Person < ActiveRecord::Base
@@ -675,17 +711,35 @@ module ActiveRecord
675
711
  #
676
712
  # person.pets.select(:name).distinct
677
713
  # # => [#<Pet name: "Fancy-Fancy">]
678
- def distinct
679
- @association.distinct
714
+ #
715
+ # person.pets.select(:name).distinct.distinct(false)
716
+ # # => [
717
+ # # #<Pet name: "Fancy-Fancy">,
718
+ # # #<Pet name: "Fancy-Fancy">
719
+ # # ]
720
+
721
+ #--
722
+ def calculate(operation, column_name)
723
+ null_scope? ? scope.calculate(operation, column_name) : super
724
+ end
725
+
726
+ def pluck(*column_names)
727
+ null_scope? ? scope.pluck(*column_names) : super
680
728
  end
681
- alias uniq distinct
682
729
 
683
- # Count all records using SQL.
730
+ ##
731
+ # :method: count
732
+ #
733
+ # :call-seq:
734
+ # count(column_name = nil, &block)
735
+ #
736
+ # Count all records.
684
737
  #
685
738
  # class Person < ActiveRecord::Base
686
739
  # has_many :pets
687
740
  # end
688
741
  #
742
+ # # This will perform the count using SQL.
689
743
  # person.pets.count # => 3
690
744
  # person.pets
691
745
  # # => [
@@ -693,11 +747,11 @@ module ActiveRecord
693
747
  # # #<Pet id: 2, name: "Spook", person_id: 1>,
694
748
  # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
695
749
  # # ]
696
- def count(column_name = nil, options = {})
697
- # TODO: Remove options argument as soon we remove support to
698
- # activerecord-deprecated_finders.
699
- @association.count(column_name, options)
700
- end
750
+ #
751
+ # Passing a block will select all of a person's pets in SQL and then
752
+ # perform the count using Ruby.
753
+ #
754
+ # person.pets.count { |pet| pet.name.include?('-') } # => 2
701
755
 
702
756
  # Returns the size of the collection. If the collection hasn't been loaded,
703
757
  # it executes a <tt>SELECT COUNT(*)</tt> query. Else it calls <tt>collection.size</tt>.
@@ -727,6 +781,12 @@ module ActiveRecord
727
781
  @association.size
728
782
  end
729
783
 
784
+ ##
785
+ # :method: length
786
+ #
787
+ # :call-seq:
788
+ # length()
789
+ #
730
790
  # Returns the size of the collection calling +size+ on the target.
731
791
  # If the collection has been already loaded, +length+ and +size+ are
732
792
  # equivalent. If not and you are going to need the records anyway this
@@ -747,14 +807,11 @@ module ActiveRecord
747
807
  # # #<Pet id: 2, name: "Spook", person_id: 1>,
748
808
  # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
749
809
  # # ]
750
- def length
751
- @association.length
752
- end
753
810
 
754
811
  # Returns +true+ if the collection is empty. If the collection has been
755
812
  # loaded it is equivalent
756
813
  # to <tt>collection.size.zero?</tt>. If the collection has not been loaded,
757
- # it is equivalent to <tt>collection.exists?</tt>. If the collection has
814
+ # it is equivalent to <tt>!collection.exists?</tt>. If the collection has
758
815
  # not already been loaded and you are going to fetch the records anyway it
759
816
  # is better to check <tt>collection.length.zero?</tt>.
760
817
  #
@@ -773,6 +830,12 @@ module ActiveRecord
773
830
  @association.empty?
774
831
  end
775
832
 
833
+ ##
834
+ # :method: any?
835
+ #
836
+ # :call-seq:
837
+ # any?()
838
+ #
776
839
  # Returns +true+ if the collection is not empty.
777
840
  #
778
841
  # class Person < ActiveRecord::Base
@@ -783,7 +846,7 @@ module ActiveRecord
783
846
  # person.pets.any? # => false
784
847
  #
785
848
  # person.pets << Pet.new(name: 'Snoop')
786
- # person.pets.count # => 0
849
+ # person.pets.count # => 1
787
850
  # person.pets.any? # => true
788
851
  #
789
852
  # You can also pass a +block+ to define criteria. The behavior
@@ -802,10 +865,13 @@ module ActiveRecord
802
865
  # pet.group == 'dogs'
803
866
  # end
804
867
  # # => true
805
- def any?(&block)
806
- @association.any?(&block)
807
- end
808
868
 
869
+ ##
870
+ # :method: many?
871
+ #
872
+ # :call-seq:
873
+ # many?()
874
+ #
809
875
  # Returns true if the collection has more than one record.
810
876
  # Equivalent to <tt>collection.size > 1</tt>.
811
877
  #
@@ -840,9 +906,6 @@ module ActiveRecord
840
906
  # pet.group == 'cats'
841
907
  # end
842
908
  # # => true
843
- def many?(&block)
844
- @association.many?(&block)
845
- end
846
909
 
847
910
  # Returns +true+ if the given +record+ is present in the collection.
848
911
  #
@@ -858,27 +921,14 @@ module ActiveRecord
858
921
  !!@association.include?(record)
859
922
  end
860
923
 
861
- def arel
862
- scope.arel
863
- end
864
-
865
- def proxy_association
924
+ def proxy_association # :nodoc:
866
925
  @association
867
926
  end
868
927
 
869
- # We don't want this object to be put on the scoping stack, because
870
- # that could create an infinite loop where we call an @association
871
- # method, which gets the current scope, which is this object, which
872
- # delegates to @association, and so on.
873
- def scoping
874
- @association.scope.scoping { yield }
875
- end
876
-
877
928
  # Returns a <tt>Relation</tt> object for the records in this association
878
929
  def scope
879
- @association.scope
930
+ @scope ||= @association.scope
880
931
  end
881
- alias spawn scope
882
932
 
883
933
  # Equivalent to <tt>Array#==</tt>. Returns +true+ if the two arrays
884
934
  # contain the same number of elements and if each element is equal
@@ -908,6 +958,12 @@ module ActiveRecord
908
958
  load_target == other
909
959
  end
910
960
 
961
+ ##
962
+ # :method: to_ary
963
+ #
964
+ # :call-seq:
965
+ # to_ary()
966
+ #
911
967
  # Returns a new array of objects from the collection. If the collection
912
968
  # hasn't been loaded, it fetches the records from the database.
913
969
  #
@@ -941,14 +997,15 @@ module ActiveRecord
941
997
  # # #<Pet id: 5, name: "Brain", person_id: 1>,
942
998
  # # #<Pet id: 6, name: "Boss", person_id: 1>
943
999
  # # ]
944
- def to_ary
945
- load_target.dup
1000
+
1001
+ def records # :nodoc:
1002
+ load_target
946
1003
  end
947
- alias_method :to_a, :to_ary
948
1004
 
949
1005
  # Adds one or more +records+ to the collection by setting their foreign keys
950
- # to the association's primary key. Returns +self+, so several appends may be
951
- # chained together.
1006
+ # to the association's primary key. Since <tt><<</tt> flattens its argument list and
1007
+ # inserts each record, +push+ and +concat+ behave identically. Returns +self+
1008
+ # so several appends may be chained together.
952
1009
  #
953
1010
  # class Person < ActiveRecord::Base
954
1011
  # has_many :pets
@@ -971,21 +1028,24 @@ module ActiveRecord
971
1028
  end
972
1029
  alias_method :push, :<<
973
1030
  alias_method :append, :<<
1031
+ alias_method :concat, :<<
974
1032
 
975
- def prepend(*args)
976
- raise NoMethodError, "prepend on association is not defined. Please use << or append"
1033
+ def prepend(*args) # :nodoc:
1034
+ raise NoMethodError, "prepend on association is not defined. Please use <<, push or append"
977
1035
  end
978
1036
 
979
1037
  # Equivalent to +delete_all+. The difference is that returns +self+, instead
980
1038
  # of an array with the deleted objects, so methods can be chained. See
981
1039
  # +delete_all+ for more information.
1040
+ # Note that because +delete_all+ removes records by directly
1041
+ # running an SQL query into the database, the +updated_at+ column of
1042
+ # the object is not changed.
982
1043
  def clear
983
1044
  delete_all
984
1045
  self
985
1046
  end
986
1047
 
987
1048
  # Reloads the collection from the database. Returns +self+.
988
- # Equivalent to <tt>collection(true)</tt>.
989
1049
  #
990
1050
  # class Person < ActiveRecord::Base
991
1051
  # has_many :pets
@@ -999,12 +1059,9 @@ module ActiveRecord
999
1059
  #
1000
1060
  # person.pets.reload # fetches pets from the database
1001
1061
  # # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
1002
- #
1003
- # person.pets(true) # fetches pets from the database
1004
- # # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
1005
1062
  def reload
1006
- proxy_association.reload
1007
- self
1063
+ proxy_association.reload(true)
1064
+ reset_scope
1008
1065
  end
1009
1066
 
1010
1067
  # Unloads the association. Returns +self+.
@@ -1026,8 +1083,53 @@ module ActiveRecord
1026
1083
  def reset
1027
1084
  proxy_association.reset
1028
1085
  proxy_association.reset_scope
1086
+ reset_scope
1087
+ end
1088
+
1089
+ def reset_scope # :nodoc:
1090
+ @offsets = @take = nil
1091
+ @scope = nil
1029
1092
  self
1030
1093
  end
1094
+
1095
+ def inspect # :nodoc:
1096
+ load_target if find_from_target?
1097
+ super
1098
+ end
1099
+
1100
+ delegate_methods = [
1101
+ QueryMethods,
1102
+ SpawnMethods,
1103
+ ].flat_map { |klass|
1104
+ klass.public_instance_methods(false)
1105
+ } - self.public_instance_methods(false) - [:select] + [
1106
+ :scoping, :values, :insert, :insert_all, :insert!, :insert_all!, :upsert, :upsert_all
1107
+ ]
1108
+
1109
+ delegate(*delegate_methods, to: :scope)
1110
+
1111
+ private
1112
+ def find_nth_with_limit(index, limit)
1113
+ load_target if find_from_target?
1114
+ super
1115
+ end
1116
+
1117
+ def find_nth_from_last(index)
1118
+ load_target if find_from_target?
1119
+ super
1120
+ end
1121
+
1122
+ def null_scope?
1123
+ @association.null_scope?
1124
+ end
1125
+
1126
+ def find_from_target?
1127
+ @association.find_from_target?
1128
+ end
1129
+
1130
+ def exec_queries
1131
+ load_target
1132
+ end
1031
1133
  end
1032
1134
  end
1033
1135
  end