activerecord 4.2.11.3 → 6.0.0

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 (372) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +613 -1643
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +13 -12
  5. data/examples/performance.rb +33 -32
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record.rb +41 -22
  8. data/lib/active_record/aggregations.rb +267 -251
  9. data/lib/active_record/association_relation.rb +11 -6
  10. data/lib/active_record/associations.rb +1737 -1597
  11. data/lib/active_record/associations/alias_tracker.rb +29 -35
  12. data/lib/active_record/associations/association.rb +125 -58
  13. data/lib/active_record/associations/association_scope.rb +103 -132
  14. data/lib/active_record/associations/belongs_to_association.rb +65 -60
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
  16. data/lib/active_record/associations/builder/association.rb +27 -40
  17. data/lib/active_record/associations/builder/belongs_to.rb +69 -55
  18. data/lib/active_record/associations/builder/collection_association.rb +10 -33
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +52 -66
  20. data/lib/active_record/associations/builder/has_many.rb +8 -4
  21. data/lib/active_record/associations/builder/has_one.rb +46 -5
  22. data/lib/active_record/associations/builder/singular_association.rb +16 -10
  23. data/lib/active_record/associations/collection_association.rb +131 -287
  24. data/lib/active_record/associations/collection_proxy.rb +241 -146
  25. data/lib/active_record/associations/foreign_association.rb +10 -1
  26. data/lib/active_record/associations/has_many_association.rb +34 -97
  27. data/lib/active_record/associations/has_many_through_association.rb +60 -87
  28. data/lib/active_record/associations/has_one_association.rb +61 -49
  29. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  30. data/lib/active_record/associations/join_dependency.rb +137 -167
  31. data/lib/active_record/associations/join_dependency/join_association.rb +38 -86
  32. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  33. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  34. data/lib/active_record/associations/preloader.rb +90 -92
  35. data/lib/active_record/associations/preloader/association.rb +90 -123
  36. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  37. data/lib/active_record/associations/singular_association.rb +18 -39
  38. data/lib/active_record/associations/through_association.rb +38 -18
  39. data/lib/active_record/attribute_assignment.rb +56 -183
  40. data/lib/active_record/attribute_decorators.rb +39 -15
  41. data/lib/active_record/attribute_methods.rb +120 -135
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -8
  43. data/lib/active_record/attribute_methods/dirty.rb +174 -144
  44. data/lib/active_record/attribute_methods/primary_key.rb +91 -83
  45. data/lib/active_record/attribute_methods/query.rb +6 -5
  46. data/lib/active_record/attribute_methods/read.rb +20 -76
  47. data/lib/active_record/attribute_methods/serialization.rb +40 -20
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +58 -36
  49. data/lib/active_record/attribute_methods/write.rb +32 -54
  50. data/lib/active_record/attributes.rb +214 -82
  51. data/lib/active_record/autosave_association.rb +91 -37
  52. data/lib/active_record/base.rb +57 -45
  53. data/lib/active_record/callbacks.rb +100 -74
  54. data/lib/active_record/coders/json.rb +3 -1
  55. data/lib/active_record/coders/yaml_column.rb +24 -12
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +796 -296
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +26 -8
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +234 -115
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +82 -23
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +170 -53
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +74 -46
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +356 -227
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +664 -243
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +191 -83
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +460 -204
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +510 -635
  69. data/lib/active_record/connection_adapters/column.rb +56 -43
  70. data/lib/active_record/connection_adapters/connection_specification.rb +174 -152
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +200 -0
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +58 -180
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +21 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -114
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
  86. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -58
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +4 -2
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +5 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -22
  93. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  94. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -3
  95. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -19
  96. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -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 +45 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  100. data/lib/active_record/connection_adapters/postgresql/oid/{integer.rb → oid.rb} +6 -2
  101. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +33 -11
  102. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -34
  103. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -5
  104. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  105. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +10 -5
  106. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +144 -47
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +470 -290
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +12 -8
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +551 -356
  117. data/lib/active_record/connection_adapters/schema_cache.rb +72 -25
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
  119. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
  120. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  121. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +103 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  126. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +290 -345
  127. data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
  128. data/lib/active_record/connection_handling.rb +176 -41
  129. data/lib/active_record/core.rb +251 -231
  130. data/lib/active_record/counter_cache.rb +67 -49
  131. data/lib/active_record/database_configurations.rb +233 -0
  132. data/lib/active_record/database_configurations/database_config.rb +37 -0
  133. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  134. data/lib/active_record/database_configurations/url_config.rb +79 -0
  135. data/lib/active_record/define_callbacks.rb +22 -0
  136. data/lib/active_record/dynamic_matchers.rb +87 -105
  137. data/lib/active_record/enum.rb +163 -86
  138. data/lib/active_record/errors.rb +188 -53
  139. data/lib/active_record/explain.rb +23 -11
  140. data/lib/active_record/explain_registry.rb +4 -2
  141. data/lib/active_record/explain_subscriber.rb +10 -5
  142. data/lib/active_record/fixture_set/file.rb +35 -9
  143. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  144. data/lib/active_record/fixture_set/render_context.rb +17 -0
  145. data/lib/active_record/fixture_set/table_row.rb +153 -0
  146. data/lib/active_record/fixture_set/table_rows.rb +47 -0
  147. data/lib/active_record/fixtures.rb +228 -499
  148. data/lib/active_record/gem_version.rb +6 -4
  149. data/lib/active_record/inheritance.rb +158 -112
  150. data/lib/active_record/insert_all.rb +179 -0
  151. data/lib/active_record/integration.rb +123 -29
  152. data/lib/active_record/internal_metadata.rb +53 -0
  153. data/lib/active_record/legacy_yaml_adapter.rb +21 -3
  154. data/lib/active_record/locale/en.yml +3 -2
  155. data/lib/active_record/locking/optimistic.rb +87 -96
  156. data/lib/active_record/locking/pessimistic.rb +18 -6
  157. data/lib/active_record/log_subscriber.rb +76 -33
  158. data/lib/active_record/middleware/database_selector.rb +75 -0
  159. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  160. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  161. data/lib/active_record/migration.rb +621 -303
  162. data/lib/active_record/migration/command_recorder.rb +177 -90
  163. data/lib/active_record/migration/compatibility.rb +244 -0
  164. data/lib/active_record/migration/join_table.rb +8 -6
  165. data/lib/active_record/model_schema.rb +312 -112
  166. data/lib/active_record/nested_attributes.rb +264 -222
  167. data/lib/active_record/no_touching.rb +14 -1
  168. data/lib/active_record/null_relation.rb +24 -37
  169. data/lib/active_record/persistence.rb +557 -125
  170. data/lib/active_record/query_cache.rb +19 -23
  171. data/lib/active_record/querying.rb +43 -29
  172. data/lib/active_record/railtie.rb +143 -44
  173. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  174. data/lib/active_record/railties/console_sandbox.rb +2 -0
  175. data/lib/active_record/railties/controller_runtime.rb +34 -33
  176. data/lib/active_record/railties/databases.rake +328 -185
  177. data/lib/active_record/readonly_attributes.rb +5 -4
  178. data/lib/active_record/reflection.rb +428 -279
  179. data/lib/active_record/relation.rb +518 -341
  180. data/lib/active_record/relation/batches.rb +207 -55
  181. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  182. data/lib/active_record/relation/calculations.rb +267 -253
  183. data/lib/active_record/relation/delegation.rb +70 -80
  184. data/lib/active_record/relation/finder_methods.rb +277 -241
  185. data/lib/active_record/relation/from_clause.rb +26 -0
  186. data/lib/active_record/relation/merger.rb +78 -87
  187. data/lib/active_record/relation/predicate_builder.rb +114 -119
  188. data/lib/active_record/relation/predicate_builder/array_handler.rb +27 -26
  189. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  190. data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
  191. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  192. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  193. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  194. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  195. data/lib/active_record/relation/query_attribute.rb +50 -0
  196. data/lib/active_record/relation/query_methods.rb +575 -394
  197. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  198. data/lib/active_record/relation/spawn_methods.rb +11 -13
  199. data/lib/active_record/relation/where_clause.rb +190 -0
  200. data/lib/active_record/relation/where_clause_factory.rb +33 -0
  201. data/lib/active_record/result.rb +79 -42
  202. data/lib/active_record/runtime_registry.rb +6 -4
  203. data/lib/active_record/sanitization.rb +144 -121
  204. data/lib/active_record/schema.rb +21 -24
  205. data/lib/active_record/schema_dumper.rb +112 -93
  206. data/lib/active_record/schema_migration.rb +24 -17
  207. data/lib/active_record/scoping.rb +45 -26
  208. data/lib/active_record/scoping/default.rb +101 -85
  209. data/lib/active_record/scoping/named.rb +86 -33
  210. data/lib/active_record/secure_token.rb +40 -0
  211. data/lib/active_record/serialization.rb +5 -5
  212. data/lib/active_record/statement_cache.rb +73 -36
  213. data/lib/active_record/store.rb +127 -42
  214. data/lib/active_record/suppressor.rb +61 -0
  215. data/lib/active_record/table_metadata.rb +75 -0
  216. data/lib/active_record/tasks/database_tasks.rb +307 -100
  217. data/lib/active_record/tasks/mysql_database_tasks.rb +55 -99
  218. data/lib/active_record/tasks/postgresql_database_tasks.rb +81 -41
  219. data/lib/active_record/tasks/sqlite_database_tasks.rb +38 -16
  220. data/lib/active_record/test_databases.rb +23 -0
  221. data/lib/active_record/test_fixtures.rb +224 -0
  222. data/lib/active_record/timestamp.rb +86 -40
  223. data/lib/active_record/touch_later.rb +66 -0
  224. data/lib/active_record/transactions.rb +216 -150
  225. data/lib/active_record/translation.rb +3 -1
  226. data/lib/active_record/type.rb +78 -23
  227. data/lib/active_record/type/adapter_specific_registry.rb +129 -0
  228. data/lib/active_record/type/date.rb +4 -45
  229. data/lib/active_record/type/date_time.rb +4 -49
  230. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  231. data/lib/active_record/type/hash_lookup_type_map.rb +5 -3
  232. data/lib/active_record/type/internal/timezone.rb +17 -0
  233. data/lib/active_record/type/json.rb +30 -0
  234. data/lib/active_record/type/serialized.rb +24 -15
  235. data/lib/active_record/type/text.rb +2 -2
  236. data/lib/active_record/type/time.rb +11 -16
  237. data/lib/active_record/type/type_map.rb +15 -17
  238. data/lib/active_record/type/unsigned_integer.rb +9 -7
  239. data/lib/active_record/type_caster.rb +9 -0
  240. data/lib/active_record/type_caster/connection.rb +34 -0
  241. data/lib/active_record/type_caster/map.rb +20 -0
  242. data/lib/active_record/validations.rb +39 -35
  243. data/lib/active_record/validations/absence.rb +25 -0
  244. data/lib/active_record/validations/associated.rb +13 -4
  245. data/lib/active_record/validations/length.rb +26 -0
  246. data/lib/active_record/validations/presence.rb +14 -13
  247. data/lib/active_record/validations/uniqueness.rb +42 -55
  248. data/lib/active_record/version.rb +3 -1
  249. data/lib/arel.rb +51 -0
  250. data/lib/arel/alias_predication.rb +9 -0
  251. data/lib/arel/attributes.rb +22 -0
  252. data/lib/arel/attributes/attribute.rb +37 -0
  253. data/lib/arel/collectors/bind.rb +24 -0
  254. data/lib/arel/collectors/composite.rb +31 -0
  255. data/lib/arel/collectors/plain_string.rb +20 -0
  256. data/lib/arel/collectors/sql_string.rb +20 -0
  257. data/lib/arel/collectors/substitute_binds.rb +28 -0
  258. data/lib/arel/crud.rb +42 -0
  259. data/lib/arel/delete_manager.rb +18 -0
  260. data/lib/arel/errors.rb +9 -0
  261. data/lib/arel/expressions.rb +29 -0
  262. data/lib/arel/factory_methods.rb +49 -0
  263. data/lib/arel/insert_manager.rb +49 -0
  264. data/lib/arel/math.rb +45 -0
  265. data/lib/arel/nodes.rb +68 -0
  266. data/lib/arel/nodes/and.rb +32 -0
  267. data/lib/arel/nodes/ascending.rb +23 -0
  268. data/lib/arel/nodes/binary.rb +52 -0
  269. data/lib/arel/nodes/bind_param.rb +36 -0
  270. data/lib/arel/nodes/case.rb +55 -0
  271. data/lib/arel/nodes/casted.rb +50 -0
  272. data/lib/arel/nodes/comment.rb +29 -0
  273. data/lib/arel/nodes/count.rb +12 -0
  274. data/lib/arel/nodes/delete_statement.rb +45 -0
  275. data/lib/arel/nodes/descending.rb +23 -0
  276. data/lib/arel/nodes/equality.rb +18 -0
  277. data/lib/arel/nodes/extract.rb +24 -0
  278. data/lib/arel/nodes/false.rb +16 -0
  279. data/lib/arel/nodes/full_outer_join.rb +8 -0
  280. data/lib/arel/nodes/function.rb +44 -0
  281. data/lib/arel/nodes/grouping.rb +8 -0
  282. data/lib/arel/nodes/in.rb +8 -0
  283. data/lib/arel/nodes/infix_operation.rb +80 -0
  284. data/lib/arel/nodes/inner_join.rb +8 -0
  285. data/lib/arel/nodes/insert_statement.rb +37 -0
  286. data/lib/arel/nodes/join_source.rb +20 -0
  287. data/lib/arel/nodes/matches.rb +18 -0
  288. data/lib/arel/nodes/named_function.rb +23 -0
  289. data/lib/arel/nodes/node.rb +50 -0
  290. data/lib/arel/nodes/node_expression.rb +13 -0
  291. data/lib/arel/nodes/outer_join.rb +8 -0
  292. data/lib/arel/nodes/over.rb +15 -0
  293. data/lib/arel/nodes/regexp.rb +16 -0
  294. data/lib/arel/nodes/right_outer_join.rb +8 -0
  295. data/lib/arel/nodes/select_core.rb +67 -0
  296. data/lib/arel/nodes/select_statement.rb +41 -0
  297. data/lib/arel/nodes/sql_literal.rb +16 -0
  298. data/lib/arel/nodes/string_join.rb +11 -0
  299. data/lib/arel/nodes/table_alias.rb +27 -0
  300. data/lib/arel/nodes/terminal.rb +16 -0
  301. data/lib/arel/nodes/true.rb +16 -0
  302. data/lib/arel/nodes/unary.rb +45 -0
  303. data/lib/arel/nodes/unary_operation.rb +20 -0
  304. data/lib/arel/nodes/unqualified_column.rb +22 -0
  305. data/lib/arel/nodes/update_statement.rb +41 -0
  306. data/lib/arel/nodes/values_list.rb +9 -0
  307. data/lib/arel/nodes/window.rb +126 -0
  308. data/lib/arel/nodes/with.rb +11 -0
  309. data/lib/arel/order_predications.rb +13 -0
  310. data/lib/arel/predications.rb +257 -0
  311. data/lib/arel/select_manager.rb +271 -0
  312. data/lib/arel/table.rb +110 -0
  313. data/lib/arel/tree_manager.rb +72 -0
  314. data/lib/arel/update_manager.rb +34 -0
  315. data/lib/arel/visitors.rb +20 -0
  316. data/lib/arel/visitors/depth_first.rb +204 -0
  317. data/lib/arel/visitors/dot.rb +297 -0
  318. data/lib/arel/visitors/ibm_db.rb +34 -0
  319. data/lib/arel/visitors/informix.rb +62 -0
  320. data/lib/arel/visitors/mssql.rb +157 -0
  321. data/lib/arel/visitors/mysql.rb +83 -0
  322. data/lib/arel/visitors/oracle.rb +159 -0
  323. data/lib/arel/visitors/oracle12.rb +66 -0
  324. data/lib/arel/visitors/postgresql.rb +110 -0
  325. data/lib/arel/visitors/sqlite.rb +39 -0
  326. data/lib/arel/visitors/to_sql.rb +889 -0
  327. data/lib/arel/visitors/visitor.rb +46 -0
  328. data/lib/arel/visitors/where_sql.rb +23 -0
  329. data/lib/arel/window_predications.rb +9 -0
  330. data/lib/rails/generators/active_record.rb +7 -5
  331. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  332. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  333. data/lib/rails/generators/active_record/migration.rb +31 -1
  334. data/lib/rails/generators/active_record/migration/migration_generator.rb +42 -37
  335. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  336. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +11 -2
  337. data/lib/rails/generators/active_record/model/model_generator.rb +19 -22
  338. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  339. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  340. metadata +164 -59
  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_set.rb +0 -81
  350. data/lib/active_record/attribute_set/builder.rb +0 -106
  351. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
  352. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  353. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  354. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  355. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  356. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  357. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  358. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  359. data/lib/active_record/type/big_integer.rb +0 -13
  360. data/lib/active_record/type/binary.rb +0 -50
  361. data/lib/active_record/type/boolean.rb +0 -31
  362. data/lib/active_record/type/decimal.rb +0 -64
  363. data/lib/active_record/type/decorator.rb +0 -14
  364. data/lib/active_record/type/float.rb +0 -19
  365. data/lib/active_record/type/integer.rb +0 -59
  366. data/lib/active_record/type/mutable.rb +0 -16
  367. data/lib/active_record/type/numeric.rb +0 -36
  368. data/lib/active_record/type/string.rb +0 -40
  369. data/lib/active_record/type/time_value.rb +0 -38
  370. data/lib/active_record/type/value.rb +0 -110
  371. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -19
  372. 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
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
@@ -54,6 +52,12 @@ module ActiveRecord
54
52
  @association.loaded?
55
53
  end
56
54
 
55
+ ##
56
+ # :method: select
57
+ #
58
+ # :call-seq:
59
+ # select(*fields, &block)
60
+ #
57
61
  # Works in two ways.
58
62
  #
59
63
  # *First:* Specify a subset of fields to be selected from the result set.
@@ -76,7 +80,7 @@ module ActiveRecord
76
80
  # # #<Pet id: nil, name: "Choo-Choo">
77
81
  # # ]
78
82
  #
79
- # person.pets.select(:id, :name )
83
+ # person.pets.select(:id, :name)
80
84
  # # => [
81
85
  # # #<Pet id: 1, name: "Fancy-Fancy">,
82
86
  # # #<Pet id: 2, name: "Spook">,
@@ -101,18 +105,9 @@ module ActiveRecord
101
105
  # # #<Pet id: 2, name: "Spook", person_id: 1>,
102
106
  # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
103
107
  # # ]
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
108
 
114
109
  # 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>
110
+ # rules as ActiveRecord::Base.find. Returns ActiveRecord::RecordNotFound
116
111
  # error if the object cannot be found.
117
112
  #
118
113
  # class Person < ActiveRecord::Base
@@ -127,7 +122,7 @@ module ActiveRecord
127
122
  # # ]
128
123
  #
129
124
  # 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
125
+ # person.pets.find(4) # => ActiveRecord::RecordNotFound: Couldn't find Pet with 'id'=4
131
126
  #
132
127
  # person.pets.find(2) { |pet| pet.name.downcase! }
133
128
  # # => #<Pet id: 2, name: "fancy-fancy", person_id: 1>
@@ -137,10 +132,17 @@ module ActiveRecord
137
132
  # # #<Pet id: 2, name: "Spook", person_id: 1>,
138
133
  # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
139
134
  # # ]
140
- def find(*args, &block)
141
- @association.find(*args, &block)
135
+ def find(*args)
136
+ return super if block_given?
137
+ @association.find(*args)
142
138
  end
143
139
 
140
+ ##
141
+ # :method: first
142
+ #
143
+ # :call-seq:
144
+ # first(limit = nil)
145
+ #
144
146
  # Returns the first record, or the first +n+ records, from the collection.
145
147
  # If the collection is empty, the first form returns +nil+, and the second
146
148
  # form returns an empty array.
@@ -167,35 +169,63 @@ module ActiveRecord
167
169
  # another_person_without.pets # => []
168
170
  # another_person_without.pets.first # => nil
169
171
  # another_person_without.pets.first(3) # => []
170
- def first(*args)
171
- @association.first(*args)
172
- end
173
172
 
174
- # Same as +first+ except returns only the second record.
175
- def second(*args)
176
- @association.second(*args)
177
- end
173
+ ##
174
+ # :method: second
175
+ #
176
+ # :call-seq:
177
+ # second()
178
+ #
179
+ # Same as #first except returns only the second record.
178
180
 
179
- # Same as +first+ except returns only the third record.
180
- def third(*args)
181
- @association.third(*args)
182
- end
181
+ ##
182
+ # :method: third
183
+ #
184
+ # :call-seq:
185
+ # third()
186
+ #
187
+ # Same as #first except returns only the third record.
183
188
 
184
- # Same as +first+ except returns only the fourth record.
185
- def fourth(*args)
186
- @association.fourth(*args)
187
- end
189
+ ##
190
+ # :method: fourth
191
+ #
192
+ # :call-seq:
193
+ # fourth()
194
+ #
195
+ # Same as #first except returns only the fourth record.
188
196
 
189
- # Same as +first+ except returns only the fifth record.
190
- def fifth(*args)
191
- @association.fifth(*args)
192
- end
197
+ ##
198
+ # :method: fifth
199
+ #
200
+ # :call-seq:
201
+ # fifth()
202
+ #
203
+ # Same as #first except returns only the fifth record.
193
204
 
194
- # Same as +first+ except returns only the forty second record.
205
+ ##
206
+ # :method: forty_two
207
+ #
208
+ # :call-seq:
209
+ # forty_two()
210
+ #
211
+ # Same as #first except returns only the forty second record.
195
212
  # Also known as accessing "the reddit".
196
- def forty_two(*args)
197
- @association.forty_two(*args)
198
- end
213
+
214
+ ##
215
+ # :method: third_to_last
216
+ #
217
+ # :call-seq:
218
+ # third_to_last()
219
+ #
220
+ # Same as #first except returns only the third-to-last record.
221
+
222
+ ##
223
+ # :method: second_to_last
224
+ #
225
+ # :call-seq:
226
+ # second_to_last()
227
+ #
228
+ # Same as #first except returns only the second-to-last record.
199
229
 
200
230
  # Returns the last record, or the last +n+ records, from the collection.
201
231
  # If the collection is empty, the first form returns +nil+, and the second
@@ -223,12 +253,39 @@ module ActiveRecord
223
253
  # another_person_without.pets # => []
224
254
  # another_person_without.pets.last # => nil
225
255
  # another_person_without.pets.last(3) # => []
226
- def last(*args)
227
- @association.last(*args)
256
+ def last(limit = nil)
257
+ load_target if find_from_target?
258
+ super
228
259
  end
229
260
 
230
- def take(n = nil)
231
- @association.take(n)
261
+ # Gives a record (or N records if a parameter is supplied) from the collection
262
+ # using the same rules as <tt>ActiveRecord::Base.take</tt>.
263
+ #
264
+ # class Person < ActiveRecord::Base
265
+ # has_many :pets
266
+ # end
267
+ #
268
+ # person.pets
269
+ # # => [
270
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
271
+ # # #<Pet id: 2, name: "Spook", person_id: 1>,
272
+ # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
273
+ # # ]
274
+ #
275
+ # person.pets.take # => #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>
276
+ #
277
+ # person.pets.take(2)
278
+ # # => [
279
+ # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
280
+ # # #<Pet id: 2, name: "Spook", person_id: 1>
281
+ # # ]
282
+ #
283
+ # another_person_without.pets # => []
284
+ # another_person_without.pets.take # => nil
285
+ # another_person_without.pets.take(2) # => []
286
+ def take(limit = nil)
287
+ load_target if find_from_target?
288
+ super
232
289
  end
233
290
 
234
291
  # Returns a new object of the collection type that has been instantiated
@@ -290,7 +347,7 @@ module ActiveRecord
290
347
  @association.create(attributes, &block)
291
348
  end
292
349
 
293
- # Like +create+, except that if the record is invalid, raises an exception.
350
+ # Like #create, except that if the record is invalid, raises an exception.
294
351
  #
295
352
  # class Person
296
353
  # has_many :pets
@@ -306,34 +363,6 @@ module ActiveRecord
306
363
  @association.create!(attributes, &block)
307
364
  end
308
365
 
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
366
  # Replaces this collection with +other_array+. This will perform a diff
338
367
  # and delete/add only records that have changed.
339
368
  #
@@ -364,7 +393,7 @@ module ActiveRecord
364
393
  # specified by the +:dependent+ option. If no +:dependent+ option is given,
365
394
  # then it will follow the default strategy.
366
395
  #
367
- # For +has_many :through+ associations, the default deletion strategy is
396
+ # For <tt>has_many :through</tt> associations, the default deletion strategy is
368
397
  # +:delete_all+.
369
398
  #
370
399
  # For +has_many+ associations, the default deletion strategy is +:nullify+.
@@ -399,7 +428,7 @@ module ActiveRecord
399
428
  # # #<Pet id: 3, name: "Choo-Choo", person_id: nil>
400
429
  # # ]
401
430
  #
402
- # Both +has_many+ and +has_many :through+ dependencies default to the
431
+ # Both +has_many+ and <tt>has_many :through</tt> dependencies default to the
403
432
  # +:delete_all+ strategy if the +:dependent+ option is set to +:destroy+.
404
433
  # Records are not instantiated and callbacks will not be fired.
405
434
  #
@@ -418,7 +447,7 @@ module ActiveRecord
418
447
  # person.pets.delete_all
419
448
  #
420
449
  # Pet.find(1, 2, 3)
421
- # # => ActiveRecord::RecordNotFound
450
+ # # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
422
451
  #
423
452
  # If it is set to <tt>:delete_all</tt>, all the objects are deleted
424
453
  # *without* calling their +destroy+ method.
@@ -438,9 +467,9 @@ module ActiveRecord
438
467
  # person.pets.delete_all
439
468
  #
440
469
  # Pet.find(1, 2, 3)
441
- # # => ActiveRecord::RecordNotFound
470
+ # # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
442
471
  def delete_all(dependent = nil)
443
- @association.delete_all(dependent)
472
+ @association.delete_all(dependent).tap { reset_scope }
444
473
  end
445
474
 
446
475
  # Deletes the records of the collection directly from the database
@@ -467,7 +496,7 @@ module ActiveRecord
467
496
  #
468
497
  # Pet.find(1) # => Couldn't find Pet with id=1
469
498
  def destroy_all
470
- @association.destroy_all
499
+ @association.destroy_all.tap { reset_scope }
471
500
  end
472
501
 
473
502
  # Deletes the +records+ supplied from the collection according to the strategy
@@ -475,7 +504,7 @@ module ActiveRecord
475
504
  # then it will follow the default strategy. Returns an array with the
476
505
  # deleted records.
477
506
  #
478
- # For +has_many :through+ associations, the default deletion strategy is
507
+ # For <tt>has_many :through</tt> associations, the default deletion strategy is
479
508
  # +:delete_all+.
480
509
  #
481
510
  # For +has_many+ associations, the default deletion strategy is +:nullify+.
@@ -532,7 +561,7 @@ module ActiveRecord
532
561
  # # => [#<Pet id: 2, name: "Spook", person_id: 1>]
533
562
  #
534
563
  # Pet.find(1, 3)
535
- # # => ActiveRecord::RecordNotFound: Couldn't find all Pets with IDs (1, 3)
564
+ # # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 3)
536
565
  #
537
566
  # If it is set to <tt>:delete_all</tt>, all the +records+ are deleted
538
567
  # *without* calling their +destroy+ method.
@@ -560,7 +589,7 @@ module ActiveRecord
560
589
  # # ]
561
590
  #
562
591
  # Pet.find(1)
563
- # # => ActiveRecord::RecordNotFound: Couldn't find Pet with id=1
592
+ # # => ActiveRecord::RecordNotFound: Couldn't find Pet with 'id'=1
564
593
  #
565
594
  # You can pass +Integer+ or +String+ values, it finds the records
566
595
  # responding to the +id+ and executes delete on them.
@@ -586,7 +615,7 @@ module ActiveRecord
586
615
  # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
587
616
  # # ]
588
617
  def delete(*records)
589
- @association.delete(*records)
618
+ @association.delete(*records).tap { reset_scope }
590
619
  end
591
620
 
592
621
  # Destroys the +records+ supplied and removes them from the collection.
@@ -624,7 +653,7 @@ module ActiveRecord
624
653
  # person.pets.size # => 0
625
654
  # person.pets # => []
626
655
  #
627
- # Pet.find(1, 2, 3) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with IDs (1, 2, 3)
656
+ # Pet.find(1, 2, 3) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
628
657
  #
629
658
  # You can pass +Integer+ or +String+ values, it finds the records
630
659
  # responding to the +id+ and then deletes them from the database.
@@ -656,11 +685,17 @@ module ActiveRecord
656
685
  # person.pets.size # => 0
657
686
  # person.pets # => []
658
687
  #
659
- # Pet.find(4, 5, 6) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with IDs (4, 5, 6)
688
+ # Pet.find(4, 5, 6) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (4, 5, 6)
660
689
  def destroy(*records)
661
- @association.destroy(*records)
690
+ @association.destroy(*records).tap { reset_scope }
662
691
  end
663
692
 
693
+ ##
694
+ # :method: distinct
695
+ #
696
+ # :call-seq:
697
+ # distinct(value = true)
698
+ #
664
699
  # Specifies whether the records should be unique or not.
665
700
  #
666
701
  # class Person < ActiveRecord::Base
@@ -675,17 +710,35 @@ module ActiveRecord
675
710
  #
676
711
  # person.pets.select(:name).distinct
677
712
  # # => [#<Pet name: "Fancy-Fancy">]
678
- def distinct
679
- @association.distinct
713
+ #
714
+ # person.pets.select(:name).distinct.distinct(false)
715
+ # # => [
716
+ # # #<Pet name: "Fancy-Fancy">,
717
+ # # #<Pet name: "Fancy-Fancy">
718
+ # # ]
719
+
720
+ #--
721
+ def calculate(operation, column_name)
722
+ null_scope? ? scope.calculate(operation, column_name) : super
723
+ end
724
+
725
+ def pluck(*column_names)
726
+ null_scope? ? scope.pluck(*column_names) : super
680
727
  end
681
- alias uniq distinct
682
728
 
683
- # Count all records using SQL.
729
+ ##
730
+ # :method: count
731
+ #
732
+ # :call-seq:
733
+ # count(column_name = nil, &block)
734
+ #
735
+ # Count all records.
684
736
  #
685
737
  # class Person < ActiveRecord::Base
686
738
  # has_many :pets
687
739
  # end
688
740
  #
741
+ # # This will perform the count using SQL.
689
742
  # person.pets.count # => 3
690
743
  # person.pets
691
744
  # # => [
@@ -693,11 +746,11 @@ module ActiveRecord
693
746
  # # #<Pet id: 2, name: "Spook", person_id: 1>,
694
747
  # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
695
748
  # # ]
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
749
+ #
750
+ # Passing a block will select all of a person's pets in SQL and then
751
+ # perform the count using Ruby.
752
+ #
753
+ # person.pets.count { |pet| pet.name.include?('-') } # => 2
701
754
 
702
755
  # Returns the size of the collection. If the collection hasn't been loaded,
703
756
  # it executes a <tt>SELECT COUNT(*)</tt> query. Else it calls <tt>collection.size</tt>.
@@ -727,6 +780,12 @@ module ActiveRecord
727
780
  @association.size
728
781
  end
729
782
 
783
+ ##
784
+ # :method: length
785
+ #
786
+ # :call-seq:
787
+ # length()
788
+ #
730
789
  # Returns the size of the collection calling +size+ on the target.
731
790
  # If the collection has been already loaded, +length+ and +size+ are
732
791
  # equivalent. If not and you are going to need the records anyway this
@@ -747,14 +806,11 @@ module ActiveRecord
747
806
  # # #<Pet id: 2, name: "Spook", person_id: 1>,
748
807
  # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
749
808
  # # ]
750
- def length
751
- @association.length
752
- end
753
809
 
754
810
  # Returns +true+ if the collection is empty. If the collection has been
755
811
  # loaded it is equivalent
756
812
  # 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
813
+ # it is equivalent to <tt>!collection.exists?</tt>. If the collection has
758
814
  # not already been loaded and you are going to fetch the records anyway it
759
815
  # is better to check <tt>collection.length.zero?</tt>.
760
816
  #
@@ -773,6 +829,12 @@ module ActiveRecord
773
829
  @association.empty?
774
830
  end
775
831
 
832
+ ##
833
+ # :method: any?
834
+ #
835
+ # :call-seq:
836
+ # any?()
837
+ #
776
838
  # Returns +true+ if the collection is not empty.
777
839
  #
778
840
  # class Person < ActiveRecord::Base
@@ -783,7 +845,7 @@ module ActiveRecord
783
845
  # person.pets.any? # => false
784
846
  #
785
847
  # person.pets << Pet.new(name: 'Snoop')
786
- # person.pets.count # => 0
848
+ # person.pets.count # => 1
787
849
  # person.pets.any? # => true
788
850
  #
789
851
  # You can also pass a +block+ to define criteria. The behavior
@@ -802,10 +864,13 @@ module ActiveRecord
802
864
  # pet.group == 'dogs'
803
865
  # end
804
866
  # # => true
805
- def any?(&block)
806
- @association.any?(&block)
807
- end
808
867
 
868
+ ##
869
+ # :method: many?
870
+ #
871
+ # :call-seq:
872
+ # many?()
873
+ #
809
874
  # Returns true if the collection has more than one record.
810
875
  # Equivalent to <tt>collection.size > 1</tt>.
811
876
  #
@@ -840,9 +905,6 @@ module ActiveRecord
840
905
  # pet.group == 'cats'
841
906
  # end
842
907
  # # => true
843
- def many?(&block)
844
- @association.many?(&block)
845
- end
846
908
 
847
909
  # Returns +true+ if the given +record+ is present in the collection.
848
910
  #
@@ -858,27 +920,14 @@ module ActiveRecord
858
920
  !!@association.include?(record)
859
921
  end
860
922
 
861
- def arel
862
- scope.arel
863
- end
864
-
865
923
  def proxy_association
866
924
  @association
867
925
  end
868
926
 
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
927
  # Returns a <tt>Relation</tt> object for the records in this association
878
928
  def scope
879
- @association.scope
929
+ @scope ||= @association.scope
880
930
  end
881
- alias spawn scope
882
931
 
883
932
  # Equivalent to <tt>Array#==</tt>. Returns +true+ if the two arrays
884
933
  # contain the same number of elements and if each element is equal
@@ -908,6 +957,12 @@ module ActiveRecord
908
957
  load_target == other
909
958
  end
910
959
 
960
+ ##
961
+ # :method: to_ary
962
+ #
963
+ # :call-seq:
964
+ # to_ary()
965
+ #
911
966
  # Returns a new array of objects from the collection. If the collection
912
967
  # hasn't been loaded, it fetches the records from the database.
913
968
  #
@@ -941,14 +996,15 @@ module ActiveRecord
941
996
  # # #<Pet id: 5, name: "Brain", person_id: 1>,
942
997
  # # #<Pet id: 6, name: "Boss", person_id: 1>
943
998
  # # ]
944
- def to_ary
945
- load_target.dup
999
+
1000
+ def records # :nodoc:
1001
+ load_target
946
1002
  end
947
- alias_method :to_a, :to_ary
948
1003
 
949
1004
  # 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.
1005
+ # to the association's primary key. Since <tt><<</tt> flattens its argument list and
1006
+ # inserts each record, +push+ and +concat+ behave identically. Returns +self+
1007
+ # so several appends may be chained together.
952
1008
  #
953
1009
  # class Person < ActiveRecord::Base
954
1010
  # has_many :pets
@@ -971,21 +1027,24 @@ module ActiveRecord
971
1027
  end
972
1028
  alias_method :push, :<<
973
1029
  alias_method :append, :<<
1030
+ alias_method :concat, :<<
974
1031
 
975
- def prepend(*args)
976
- raise NoMethodError, "prepend on association is not defined. Please use << or append"
1032
+ def prepend(*args) # :nodoc:
1033
+ raise NoMethodError, "prepend on association is not defined. Please use <<, push or append"
977
1034
  end
978
1035
 
979
1036
  # Equivalent to +delete_all+. The difference is that returns +self+, instead
980
1037
  # of an array with the deleted objects, so methods can be chained. See
981
1038
  # +delete_all+ for more information.
1039
+ # Note that because +delete_all+ removes records by directly
1040
+ # running an SQL query into the database, the +updated_at+ column of
1041
+ # the object is not changed.
982
1042
  def clear
983
1043
  delete_all
984
1044
  self
985
1045
  end
986
1046
 
987
1047
  # Reloads the collection from the database. Returns +self+.
988
- # Equivalent to <tt>collection(true)</tt>.
989
1048
  #
990
1049
  # class Person < ActiveRecord::Base
991
1050
  # has_many :pets
@@ -999,12 +1058,9 @@ module ActiveRecord
999
1058
  #
1000
1059
  # person.pets.reload # fetches pets from the database
1001
1060
  # # => [#<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
1061
  def reload
1006
- proxy_association.reload
1007
- self
1062
+ proxy_association.reload(true)
1063
+ reset_scope
1008
1064
  end
1009
1065
 
1010
1066
  # Unloads the association. Returns +self+.
@@ -1026,8 +1082,47 @@ module ActiveRecord
1026
1082
  def reset
1027
1083
  proxy_association.reset
1028
1084
  proxy_association.reset_scope
1085
+ reset_scope
1086
+ end
1087
+
1088
+ def reset_scope # :nodoc:
1089
+ @offsets = {}
1090
+ @scope = nil
1029
1091
  self
1030
1092
  end
1093
+
1094
+ delegate_methods = [
1095
+ QueryMethods,
1096
+ SpawnMethods,
1097
+ ].flat_map { |klass|
1098
+ klass.public_instance_methods(false)
1099
+ } - self.public_instance_methods(false) - [:select] + [:scoping, :values]
1100
+
1101
+ delegate(*delegate_methods, to: :scope)
1102
+
1103
+ private
1104
+
1105
+ def find_nth_with_limit(index, limit)
1106
+ load_target if find_from_target?
1107
+ super
1108
+ end
1109
+
1110
+ def find_nth_from_last(index)
1111
+ load_target if find_from_target?
1112
+ super
1113
+ end
1114
+
1115
+ def null_scope?
1116
+ @association.null_scope?
1117
+ end
1118
+
1119
+ def find_from_target?
1120
+ @association.find_from_target?
1121
+ end
1122
+
1123
+ def exec_queries
1124
+ load_target
1125
+ end
1031
1126
  end
1032
1127
  end
1033
1128
  end