activerecord 4.2.0 → 6.0.5.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 (373) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +852 -801
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +14 -13
  5. data/examples/performance.rb +33 -32
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/advisory_lock_base.rb +18 -0
  8. data/lib/active_record/aggregations.rb +267 -249
  9. data/lib/active_record/association_relation.rb +26 -6
  10. data/lib/active_record/associations/alias_tracker.rb +29 -36
  11. data/lib/active_record/associations/association.rb +137 -55
  12. data/lib/active_record/associations/association_scope.rb +110 -132
  13. data/lib/active_record/associations/belongs_to_association.rb +67 -54
  14. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
  15. data/lib/active_record/associations/builder/association.rb +27 -40
  16. data/lib/active_record/associations/builder/belongs_to.rb +69 -55
  17. data/lib/active_record/associations/builder/collection_association.rb +10 -29
  18. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +58 -70
  19. data/lib/active_record/associations/builder/has_many.rb +8 -4
  20. data/lib/active_record/associations/builder/has_one.rb +46 -5
  21. data/lib/active_record/associations/builder/singular_association.rb +16 -10
  22. data/lib/active_record/associations/collection_association.rb +150 -275
  23. data/lib/active_record/associations/collection_proxy.rb +253 -152
  24. data/lib/active_record/associations/foreign_association.rb +20 -0
  25. data/lib/active_record/associations/has_many_association.rb +35 -84
  26. data/lib/active_record/associations/has_many_through_association.rb +62 -80
  27. data/lib/active_record/associations/has_one_association.rb +62 -49
  28. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  29. data/lib/active_record/associations/join_dependency/join_association.rb +43 -78
  30. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  31. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  32. data/lib/active_record/associations/join_dependency.rb +159 -162
  33. data/lib/active_record/associations/preloader/association.rb +102 -113
  34. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  35. data/lib/active_record/associations/preloader.rb +96 -95
  36. data/lib/active_record/associations/singular_association.rb +18 -45
  37. data/lib/active_record/associations/through_association.rb +49 -24
  38. data/lib/active_record/associations.rb +1737 -1596
  39. data/lib/active_record/attribute_assignment.rb +57 -185
  40. data/lib/active_record/attribute_decorators.rb +39 -17
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +14 -5
  42. data/lib/active_record/attribute_methods/dirty.rb +174 -134
  43. data/lib/active_record/attribute_methods/primary_key.rb +90 -84
  44. data/lib/active_record/attribute_methods/query.rb +6 -5
  45. data/lib/active_record/attribute_methods/read.rb +20 -77
  46. data/lib/active_record/attribute_methods/serialization.rb +40 -21
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -37
  48. data/lib/active_record/attribute_methods/write.rb +33 -56
  49. data/lib/active_record/attribute_methods.rb +124 -143
  50. data/lib/active_record/attributes.rb +213 -74
  51. data/lib/active_record/autosave_association.rb +125 -54
  52. data/lib/active_record/base.rb +60 -49
  53. data/lib/active_record/callbacks.rb +101 -76
  54. data/lib/active_record/coders/json.rb +3 -1
  55. data/lib/active_record/coders/yaml_column.rb +36 -13
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +810 -291
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +26 -8
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +253 -108
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +83 -24
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +171 -53
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +6 -4
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +74 -47
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +383 -239
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +736 -235
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +190 -87
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +487 -192
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +536 -600
  69. data/lib/active_record/connection_adapters/column.rb +56 -43
  70. data/lib/active_record/connection_adapters/connection_specification.rb +174 -153
  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 +196 -0
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +71 -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 +268 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +59 -196
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +21 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +71 -115
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -57
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +5 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +5 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +17 -13
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +6 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -20
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  99. data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +67 -51
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +9 -5
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
  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 +49 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +465 -291
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +565 -363
  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 +119 -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 +102 -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 +299 -364
  127. data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
  128. data/lib/active_record/connection_handling.rb +167 -41
  129. data/lib/active_record/core.rb +277 -233
  130. data/lib/active_record/counter_cache.rb +71 -50
  131. data/lib/active_record/database_configurations/database_config.rb +37 -0
  132. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  133. data/lib/active_record/database_configurations/url_config.rb +78 -0
  134. data/lib/active_record/database_configurations.rb +233 -0
  135. data/lib/active_record/define_callbacks.rb +22 -0
  136. data/lib/active_record/dynamic_matchers.rb +87 -106
  137. data/lib/active_record/enum.rb +172 -89
  138. data/lib/active_record/errors.rb +189 -53
  139. data/lib/active_record/explain.rb +22 -11
  140. data/lib/active_record/explain_registry.rb +4 -2
  141. data/lib/active_record/explain_subscriber.rb +11 -6
  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 +152 -0
  146. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  147. data/lib/active_record/fixtures.rb +225 -497
  148. data/lib/active_record/gem_version.rb +6 -4
  149. data/lib/active_record/inheritance.rb +158 -115
  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 +48 -0
  154. data/lib/active_record/locale/en.yml +3 -2
  155. data/lib/active_record/locking/optimistic.rb +99 -98
  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/resolver/session.rb +45 -0
  159. data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
  160. data/lib/active_record/middleware/database_selector.rb +74 -0
  161. data/lib/active_record/migration/command_recorder.rb +166 -91
  162. data/lib/active_record/migration/compatibility.rb +244 -0
  163. data/lib/active_record/migration/join_table.rb +8 -7
  164. data/lib/active_record/migration.rb +636 -290
  165. data/lib/active_record/model_schema.rb +344 -112
  166. data/lib/active_record/nested_attributes.rb +265 -215
  167. data/lib/active_record/no_touching.rb +15 -2
  168. data/lib/active_record/null_relation.rb +24 -38
  169. data/lib/active_record/persistence.rb +559 -125
  170. data/lib/active_record/query_cache.rb +19 -23
  171. data/lib/active_record/querying.rb +44 -30
  172. data/lib/active_record/railtie.rb +166 -47
  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 +341 -202
  177. data/lib/active_record/readonly_attributes.rb +5 -4
  178. data/lib/active_record/reflection.rb +461 -302
  179. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  180. data/lib/active_record/relation/batches.rb +206 -55
  181. data/lib/active_record/relation/calculations.rb +270 -249
  182. data/lib/active_record/relation/delegation.rb +76 -84
  183. data/lib/active_record/relation/finder_methods.rb +287 -255
  184. data/lib/active_record/relation/from_clause.rb +30 -0
  185. data/lib/active_record/relation/merger.rb +86 -68
  186. data/lib/active_record/relation/predicate_builder/array_handler.rb +27 -25
  187. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  188. data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
  189. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  190. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  191. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  192. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  193. data/lib/active_record/relation/predicate_builder.rb +112 -92
  194. data/lib/active_record/relation/query_attribute.rb +50 -0
  195. data/lib/active_record/relation/query_methods.rb +612 -392
  196. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  197. data/lib/active_record/relation/spawn_methods.rb +18 -17
  198. data/lib/active_record/relation/where_clause.rb +189 -0
  199. data/lib/active_record/relation/where_clause_factory.rb +33 -0
  200. data/lib/active_record/relation.rb +533 -340
  201. data/lib/active_record/result.rb +79 -43
  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 -20
  207. data/lib/active_record/scoping/default.rb +98 -82
  208. data/lib/active_record/scoping/named.rb +91 -33
  209. data/lib/active_record/scoping.rb +45 -27
  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 +90 -0
  216. data/lib/active_record/tasks/database_tasks.rb +309 -99
  217. data/lib/active_record/tasks/mysql_database_tasks.rb +58 -89
  218. data/lib/active_record/tasks/postgresql_database_tasks.rb +81 -31
  219. data/lib/active_record/tasks/sqlite_database_tasks.rb +37 -16
  220. data/lib/active_record/test_databases.rb +23 -0
  221. data/lib/active_record/test_fixtures.rb +243 -0
  222. data/lib/active_record/timestamp.rb +86 -41
  223. data/lib/active_record/touch_later.rb +65 -0
  224. data/lib/active_record/transactions.rb +222 -146
  225. data/lib/active_record/translation.rb +3 -1
  226. data/lib/active_record/type/adapter_specific_registry.rb +126 -0
  227. data/lib/active_record/type/date.rb +4 -41
  228. data/lib/active_record/type/date_time.rb +4 -38
  229. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  230. data/lib/active_record/type/hash_lookup_type_map.rb +12 -5
  231. data/lib/active_record/type/internal/timezone.rb +17 -0
  232. data/lib/active_record/type/json.rb +30 -0
  233. data/lib/active_record/type/serialized.rb +29 -15
  234. data/lib/active_record/type/text.rb +2 -2
  235. data/lib/active_record/type/time.rb +21 -16
  236. data/lib/active_record/type/type_map.rb +16 -19
  237. data/lib/active_record/type/unsigned_integer.rb +9 -8
  238. data/lib/active_record/type.rb +77 -23
  239. data/lib/active_record/type_caster/connection.rb +34 -0
  240. data/lib/active_record/type_caster/map.rb +20 -0
  241. data/lib/active_record/type_caster.rb +9 -0
  242. data/lib/active_record/validations/absence.rb +25 -0
  243. data/lib/active_record/validations/associated.rb +12 -4
  244. data/lib/active_record/validations/length.rb +26 -0
  245. data/lib/active_record/validations/presence.rb +14 -13
  246. data/lib/active_record/validations/uniqueness.rb +43 -46
  247. data/lib/active_record/validations.rb +38 -35
  248. data/lib/active_record/version.rb +3 -1
  249. data/lib/active_record.rb +44 -21
  250. data/lib/arel/alias_predication.rb +9 -0
  251. data/lib/arel/attributes/attribute.rb +37 -0
  252. data/lib/arel/attributes.rb +22 -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/and.rb +32 -0
  266. data/lib/arel/nodes/ascending.rb +23 -0
  267. data/lib/arel/nodes/binary.rb +52 -0
  268. data/lib/arel/nodes/bind_param.rb +36 -0
  269. data/lib/arel/nodes/case.rb +55 -0
  270. data/lib/arel/nodes/casted.rb +50 -0
  271. data/lib/arel/nodes/comment.rb +29 -0
  272. data/lib/arel/nodes/count.rb +12 -0
  273. data/lib/arel/nodes/delete_statement.rb +45 -0
  274. data/lib/arel/nodes/descending.rb +23 -0
  275. data/lib/arel/nodes/equality.rb +18 -0
  276. data/lib/arel/nodes/extract.rb +24 -0
  277. data/lib/arel/nodes/false.rb +16 -0
  278. data/lib/arel/nodes/full_outer_join.rb +8 -0
  279. data/lib/arel/nodes/function.rb +44 -0
  280. data/lib/arel/nodes/grouping.rb +8 -0
  281. data/lib/arel/nodes/in.rb +8 -0
  282. data/lib/arel/nodes/infix_operation.rb +80 -0
  283. data/lib/arel/nodes/inner_join.rb +8 -0
  284. data/lib/arel/nodes/insert_statement.rb +37 -0
  285. data/lib/arel/nodes/join_source.rb +20 -0
  286. data/lib/arel/nodes/matches.rb +18 -0
  287. data/lib/arel/nodes/named_function.rb +23 -0
  288. data/lib/arel/nodes/node.rb +50 -0
  289. data/lib/arel/nodes/node_expression.rb +13 -0
  290. data/lib/arel/nodes/outer_join.rb +8 -0
  291. data/lib/arel/nodes/over.rb +15 -0
  292. data/lib/arel/nodes/regexp.rb +16 -0
  293. data/lib/arel/nodes/right_outer_join.rb +8 -0
  294. data/lib/arel/nodes/select_core.rb +67 -0
  295. data/lib/arel/nodes/select_statement.rb +41 -0
  296. data/lib/arel/nodes/sql_literal.rb +16 -0
  297. data/lib/arel/nodes/string_join.rb +11 -0
  298. data/lib/arel/nodes/table_alias.rb +27 -0
  299. data/lib/arel/nodes/terminal.rb +16 -0
  300. data/lib/arel/nodes/true.rb +16 -0
  301. data/lib/arel/nodes/unary.rb +45 -0
  302. data/lib/arel/nodes/unary_operation.rb +20 -0
  303. data/lib/arel/nodes/unqualified_column.rb +22 -0
  304. data/lib/arel/nodes/update_statement.rb +41 -0
  305. data/lib/arel/nodes/values_list.rb +9 -0
  306. data/lib/arel/nodes/window.rb +126 -0
  307. data/lib/arel/nodes/with.rb +11 -0
  308. data/lib/arel/nodes.rb +68 -0
  309. data/lib/arel/order_predications.rb +13 -0
  310. data/lib/arel/predications.rb +256 -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/depth_first.rb +203 -0
  316. data/lib/arel/visitors/dot.rb +296 -0
  317. data/lib/arel/visitors/ibm_db.rb +34 -0
  318. data/lib/arel/visitors/informix.rb +62 -0
  319. data/lib/arel/visitors/mssql.rb +156 -0
  320. data/lib/arel/visitors/mysql.rb +83 -0
  321. data/lib/arel/visitors/oracle.rb +158 -0
  322. data/lib/arel/visitors/oracle12.rb +65 -0
  323. data/lib/arel/visitors/postgresql.rb +109 -0
  324. data/lib/arel/visitors/sqlite.rb +38 -0
  325. data/lib/arel/visitors/to_sql.rb +888 -0
  326. data/lib/arel/visitors/visitor.rb +45 -0
  327. data/lib/arel/visitors/where_sql.rb +22 -0
  328. data/lib/arel/visitors.rb +20 -0
  329. data/lib/arel/window_predications.rb +9 -0
  330. data/lib/arel.rb +62 -0
  331. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -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/migration_generator.rb +42 -37
  334. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  335. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +11 -8
  336. data/lib/rails/generators/active_record/migration.rb +30 -1
  337. data/lib/rails/generators/active_record/model/model_generator.rb +18 -22
  338. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  339. data/lib/rails/generators/active_record.rb +7 -5
  340. metadata +174 -63
  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 -149
  349. data/lib/active_record/attribute_set/builder.rb +0 -86
  350. data/lib/active_record/attribute_set.rb +0 -77
  351. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  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/integer.rb +0 -11
  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 -30
  362. data/lib/active_record/type/decimal.rb +0 -40
  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 -55
  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 -36
  369. data/lib/active_record/type/time_value.rb +0 -38
  370. data/lib/active_record/type/value.rb +0 -101
  371. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -22
  372. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
  373. /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -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,26 +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
-
33
- def initialize(klass, association) #:nodoc:
30
+ def initialize(klass, association, **) #:nodoc:
34
31
  @association = association
35
- super klass, klass.arel_table
36
- merge! association.scope(nullify: false)
32
+ super klass
33
+
34
+ extensions = association.extensions
35
+ extend(*extensions) if extensions.any?
37
36
  end
38
37
 
39
38
  def target
@@ -52,7 +51,14 @@ module ActiveRecord
52
51
  def loaded?
53
52
  @association.loaded?
54
53
  end
54
+ alias :loaded :loaded?
55
55
 
56
+ ##
57
+ # :method: select
58
+ #
59
+ # :call-seq:
60
+ # select(*fields, &block)
61
+ #
56
62
  # Works in two ways.
57
63
  #
58
64
  # *First:* Specify a subset of fields to be selected from the result set.
@@ -75,7 +81,7 @@ module ActiveRecord
75
81
  # # #<Pet id: nil, name: "Choo-Choo">
76
82
  # # ]
77
83
  #
78
- # person.pets.select(:id, :name )
84
+ # person.pets.select(:id, :name)
79
85
  # # => [
80
86
  # # #<Pet id: 1, name: "Fancy-Fancy">,
81
87
  # # #<Pet id: 2, name: "Spook">,
@@ -100,18 +106,9 @@ module ActiveRecord
100
106
  # # #<Pet id: 2, name: "Spook", person_id: 1>,
101
107
  # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
102
108
  # # ]
103
- #
104
- # person.pets.select(:name) { |pet| pet.name =~ /oo/ }
105
- # # => [
106
- # # #<Pet id: 2, name: "Spook">,
107
- # # #<Pet id: 3, name: "Choo-Choo">
108
- # # ]
109
- def select(*fields, &block)
110
- @association.select(*fields, &block)
111
- end
112
109
 
113
110
  # Finds an object in the collection responding to the +id+. Uses the same
114
- # rules as <tt>ActiveRecord::Base.find</tt>. Returns <tt>ActiveRecord::RecordNotFound</tt>
111
+ # rules as ActiveRecord::Base.find. Returns ActiveRecord::RecordNotFound
115
112
  # error if the object cannot be found.
116
113
  #
117
114
  # class Person < ActiveRecord::Base
@@ -126,7 +123,7 @@ module ActiveRecord
126
123
  # # ]
127
124
  #
128
125
  # person.pets.find(1) # => #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>
129
- # 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
130
127
  #
131
128
  # person.pets.find(2) { |pet| pet.name.downcase! }
132
129
  # # => #<Pet id: 2, name: "fancy-fancy", person_id: 1>
@@ -136,10 +133,17 @@ module ActiveRecord
136
133
  # # #<Pet id: 2, name: "Spook", person_id: 1>,
137
134
  # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
138
135
  # # ]
139
- def find(*args, &block)
140
- @association.find(*args, &block)
136
+ def find(*args)
137
+ return super if block_given?
138
+ @association.find(*args)
141
139
  end
142
140
 
141
+ ##
142
+ # :method: first
143
+ #
144
+ # :call-seq:
145
+ # first(limit = nil)
146
+ #
143
147
  # Returns the first record, or the first +n+ records, from the collection.
144
148
  # If the collection is empty, the first form returns +nil+, and the second
145
149
  # form returns an empty array.
@@ -166,35 +170,63 @@ module ActiveRecord
166
170
  # another_person_without.pets # => []
167
171
  # another_person_without.pets.first # => nil
168
172
  # another_person_without.pets.first(3) # => []
169
- def first(*args)
170
- @association.first(*args)
171
- end
172
173
 
173
- # Same as +first+ except returns only the second record.
174
- def second(*args)
175
- @association.second(*args)
176
- end
174
+ ##
175
+ # :method: second
176
+ #
177
+ # :call-seq:
178
+ # second()
179
+ #
180
+ # Same as #first except returns only the second record.
177
181
 
178
- # Same as +first+ except returns only the third record.
179
- def third(*args)
180
- @association.third(*args)
181
- end
182
+ ##
183
+ # :method: third
184
+ #
185
+ # :call-seq:
186
+ # third()
187
+ #
188
+ # Same as #first except returns only the third record.
182
189
 
183
- # Same as +first+ except returns only the fourth record.
184
- def fourth(*args)
185
- @association.fourth(*args)
186
- end
190
+ ##
191
+ # :method: fourth
192
+ #
193
+ # :call-seq:
194
+ # fourth()
195
+ #
196
+ # Same as #first except returns only the fourth record.
187
197
 
188
- # Same as +first+ except returns only the fifth record.
189
- def fifth(*args)
190
- @association.fifth(*args)
191
- end
198
+ ##
199
+ # :method: fifth
200
+ #
201
+ # :call-seq:
202
+ # fifth()
203
+ #
204
+ # Same as #first except returns only the fifth record.
192
205
 
193
- # 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.
194
213
  # Also known as accessing "the reddit".
195
- def forty_two(*args)
196
- @association.forty_two(*args)
197
- 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.
198
230
 
199
231
  # Returns the last record, or the last +n+ records, from the collection.
200
232
  # If the collection is empty, the first form returns +nil+, and the second
@@ -222,8 +254,39 @@ module ActiveRecord
222
254
  # another_person_without.pets # => []
223
255
  # another_person_without.pets.last # => nil
224
256
  # another_person_without.pets.last(3) # => []
225
- def last(*args)
226
- @association.last(*args)
257
+ def last(limit = nil)
258
+ load_target if find_from_target?
259
+ super
260
+ end
261
+
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
227
290
  end
228
291
 
229
292
  # Returns a new object of the collection type that has been instantiated
@@ -285,7 +348,7 @@ module ActiveRecord
285
348
  @association.create(attributes, &block)
286
349
  end
287
350
 
288
- # 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.
289
352
  #
290
353
  # class Person
291
354
  # has_many :pets
@@ -301,34 +364,6 @@ module ActiveRecord
301
364
  @association.create!(attributes, &block)
302
365
  end
303
366
 
304
- # Add one or more records to the collection by setting their foreign keys
305
- # to the association's primary key. Since << flattens its argument list and
306
- # inserts each record, +push+ and +concat+ behave identically. Returns +self+
307
- # so method calls may be chained.
308
- #
309
- # class Person < ActiveRecord::Base
310
- # has_many :pets
311
- # end
312
- #
313
- # person.pets.size # => 0
314
- # person.pets.concat(Pet.new(name: 'Fancy-Fancy'))
315
- # person.pets.concat(Pet.new(name: 'Spook'), Pet.new(name: 'Choo-Choo'))
316
- # person.pets.size # => 3
317
- #
318
- # person.id # => 1
319
- # person.pets
320
- # # => [
321
- # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
322
- # # #<Pet id: 2, name: "Spook", person_id: 1>,
323
- # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
324
- # # ]
325
- #
326
- # person.pets.concat([Pet.new(name: 'Brain'), Pet.new(name: 'Benny')])
327
- # person.pets.size # => 5
328
- def concat(*records)
329
- @association.concat(*records)
330
- end
331
-
332
367
  # Replaces this collection with +other_array+. This will perform a diff
333
368
  # and delete/add only records that have changed.
334
369
  #
@@ -359,7 +394,7 @@ module ActiveRecord
359
394
  # specified by the +:dependent+ option. If no +:dependent+ option is given,
360
395
  # then it will follow the default strategy.
361
396
  #
362
- # For +has_many :through+ associations, the default deletion strategy is
397
+ # For <tt>has_many :through</tt> associations, the default deletion strategy is
363
398
  # +:delete_all+.
364
399
  #
365
400
  # For +has_many+ associations, the default deletion strategy is +:nullify+.
@@ -394,7 +429,7 @@ module ActiveRecord
394
429
  # # #<Pet id: 3, name: "Choo-Choo", person_id: nil>
395
430
  # # ]
396
431
  #
397
- # 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
398
433
  # +:delete_all+ strategy if the +:dependent+ option is set to +:destroy+.
399
434
  # Records are not instantiated and callbacks will not be fired.
400
435
  #
@@ -413,7 +448,7 @@ module ActiveRecord
413
448
  # person.pets.delete_all
414
449
  #
415
450
  # Pet.find(1, 2, 3)
416
- # # => ActiveRecord::RecordNotFound
451
+ # # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
417
452
  #
418
453
  # If it is set to <tt>:delete_all</tt>, all the objects are deleted
419
454
  # *without* calling their +destroy+ method.
@@ -433,9 +468,9 @@ module ActiveRecord
433
468
  # person.pets.delete_all
434
469
  #
435
470
  # Pet.find(1, 2, 3)
436
- # # => ActiveRecord::RecordNotFound
471
+ # # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
437
472
  def delete_all(dependent = nil)
438
- @association.delete_all(dependent)
473
+ @association.delete_all(dependent).tap { reset_scope }
439
474
  end
440
475
 
441
476
  # Deletes the records of the collection directly from the database
@@ -462,18 +497,19 @@ module ActiveRecord
462
497
  #
463
498
  # Pet.find(1) # => Couldn't find Pet with id=1
464
499
  def destroy_all
465
- @association.destroy_all
500
+ @association.destroy_all.tap { reset_scope }
466
501
  end
467
502
 
468
- # Deletes the +records+ supplied and removes them from the collection. For
469
- # +has_many+ associations, the deletion is done according to the strategy
470
- # specified by the <tt>:dependent</tt> option. Returns an array with the
503
+ # Deletes the +records+ supplied from the collection according to the strategy
504
+ # specified by the +:dependent+ option. If no +:dependent+ option is given,
505
+ # then it will follow the default strategy. Returns an array with the
471
506
  # deleted records.
472
507
  #
473
- # If no <tt>:dependent</tt> option is given, then it will follow the default
474
- # strategy. The default strategy is <tt>:nullify</tt>. This sets the foreign
475
- # keys to <tt>NULL</tt>. For, +has_many+ <tt>:through</tt>, the default
476
- # strategy is +delete_all+.
508
+ # For <tt>has_many :through</tt> associations, the default deletion strategy is
509
+ # +:delete_all+.
510
+ #
511
+ # For +has_many+ associations, the default deletion strategy is +:nullify+.
512
+ # This sets the foreign keys to +NULL+.
477
513
  #
478
514
  # class Person < ActiveRecord::Base
479
515
  # has_many :pets # dependent: :nullify option by default
@@ -526,7 +562,7 @@ module ActiveRecord
526
562
  # # => [#<Pet id: 2, name: "Spook", person_id: 1>]
527
563
  #
528
564
  # Pet.find(1, 3)
529
- # # => ActiveRecord::RecordNotFound: Couldn't find all Pets with IDs (1, 3)
565
+ # # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 3)
530
566
  #
531
567
  # If it is set to <tt>:delete_all</tt>, all the +records+ are deleted
532
568
  # *without* calling their +destroy+ method.
@@ -554,9 +590,9 @@ module ActiveRecord
554
590
  # # ]
555
591
  #
556
592
  # Pet.find(1)
557
- # # => ActiveRecord::RecordNotFound: Couldn't find Pet with id=1
593
+ # # => ActiveRecord::RecordNotFound: Couldn't find Pet with 'id'=1
558
594
  #
559
- # You can pass +Fixnum+ or +String+ values, it finds the records
595
+ # You can pass +Integer+ or +String+ values, it finds the records
560
596
  # responding to the +id+ and executes delete on them.
561
597
  #
562
598
  # class Person < ActiveRecord::Base
@@ -580,7 +616,7 @@ module ActiveRecord
580
616
  # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
581
617
  # # ]
582
618
  def delete(*records)
583
- @association.delete(*records)
619
+ @association.delete(*records).tap { reset_scope }
584
620
  end
585
621
 
586
622
  # Destroys the +records+ supplied and removes them from the collection.
@@ -618,9 +654,9 @@ module ActiveRecord
618
654
  # person.pets.size # => 0
619
655
  # person.pets # => []
620
656
  #
621
- # 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)
622
658
  #
623
- # You can pass +Fixnum+ or +String+ values, it finds the records
659
+ # You can pass +Integer+ or +String+ values, it finds the records
624
660
  # responding to the +id+ and then deletes them from the database.
625
661
  #
626
662
  # person.pets.size # => 3
@@ -650,11 +686,17 @@ module ActiveRecord
650
686
  # person.pets.size # => 0
651
687
  # person.pets # => []
652
688
  #
653
- # 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)
654
690
  def destroy(*records)
655
- @association.destroy(*records)
691
+ @association.destroy(*records).tap { reset_scope }
656
692
  end
657
693
 
694
+ ##
695
+ # :method: distinct
696
+ #
697
+ # :call-seq:
698
+ # distinct(value = true)
699
+ #
658
700
  # Specifies whether the records should be unique or not.
659
701
  #
660
702
  # class Person < ActiveRecord::Base
@@ -669,17 +711,35 @@ module ActiveRecord
669
711
  #
670
712
  # person.pets.select(:name).distinct
671
713
  # # => [#<Pet name: "Fancy-Fancy">]
672
- def distinct
673
- @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
674
728
  end
675
- alias uniq distinct
676
729
 
677
- # Count all records using SQL.
730
+ ##
731
+ # :method: count
732
+ #
733
+ # :call-seq:
734
+ # count(column_name = nil, &block)
735
+ #
736
+ # Count all records.
678
737
  #
679
738
  # class Person < ActiveRecord::Base
680
739
  # has_many :pets
681
740
  # end
682
741
  #
742
+ # # This will perform the count using SQL.
683
743
  # person.pets.count # => 3
684
744
  # person.pets
685
745
  # # => [
@@ -687,11 +747,11 @@ module ActiveRecord
687
747
  # # #<Pet id: 2, name: "Spook", person_id: 1>,
688
748
  # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
689
749
  # # ]
690
- def count(column_name = nil, options = {})
691
- # TODO: Remove options argument as soon we remove support to
692
- # activerecord-deprecated_finders.
693
- @association.count(column_name, options)
694
- 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
695
755
 
696
756
  # Returns the size of the collection. If the collection hasn't been loaded,
697
757
  # it executes a <tt>SELECT COUNT(*)</tt> query. Else it calls <tt>collection.size</tt>.
@@ -721,6 +781,12 @@ module ActiveRecord
721
781
  @association.size
722
782
  end
723
783
 
784
+ ##
785
+ # :method: length
786
+ #
787
+ # :call-seq:
788
+ # length()
789
+ #
724
790
  # Returns the size of the collection calling +size+ on the target.
725
791
  # If the collection has been already loaded, +length+ and +size+ are
726
792
  # equivalent. If not and you are going to need the records anyway this
@@ -741,14 +807,11 @@ module ActiveRecord
741
807
  # # #<Pet id: 2, name: "Spook", person_id: 1>,
742
808
  # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
743
809
  # # ]
744
- def length
745
- @association.length
746
- end
747
810
 
748
811
  # Returns +true+ if the collection is empty. If the collection has been
749
812
  # loaded it is equivalent
750
813
  # to <tt>collection.size.zero?</tt>. If the collection has not been loaded,
751
- # 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
752
815
  # not already been loaded and you are going to fetch the records anyway it
753
816
  # is better to check <tt>collection.length.zero?</tt>.
754
817
  #
@@ -767,6 +830,12 @@ module ActiveRecord
767
830
  @association.empty?
768
831
  end
769
832
 
833
+ ##
834
+ # :method: any?
835
+ #
836
+ # :call-seq:
837
+ # any?()
838
+ #
770
839
  # Returns +true+ if the collection is not empty.
771
840
  #
772
841
  # class Person < ActiveRecord::Base
@@ -777,7 +846,7 @@ module ActiveRecord
777
846
  # person.pets.any? # => false
778
847
  #
779
848
  # person.pets << Pet.new(name: 'Snoop')
780
- # person.pets.count # => 0
849
+ # person.pets.count # => 1
781
850
  # person.pets.any? # => true
782
851
  #
783
852
  # You can also pass a +block+ to define criteria. The behavior
@@ -796,10 +865,13 @@ module ActiveRecord
796
865
  # pet.group == 'dogs'
797
866
  # end
798
867
  # # => true
799
- def any?(&block)
800
- @association.any?(&block)
801
- end
802
868
 
869
+ ##
870
+ # :method: many?
871
+ #
872
+ # :call-seq:
873
+ # many?()
874
+ #
803
875
  # Returns true if the collection has more than one record.
804
876
  # Equivalent to <tt>collection.size > 1</tt>.
805
877
  #
@@ -834,9 +906,6 @@ module ActiveRecord
834
906
  # pet.group == 'cats'
835
907
  # end
836
908
  # # => true
837
- def many?(&block)
838
- @association.many?(&block)
839
- end
840
909
 
841
910
  # Returns +true+ if the given +record+ is present in the collection.
842
911
  #
@@ -852,27 +921,14 @@ module ActiveRecord
852
921
  !!@association.include?(record)
853
922
  end
854
923
 
855
- def arel
856
- scope.arel
857
- end
858
-
859
924
  def proxy_association
860
925
  @association
861
926
  end
862
927
 
863
- # We don't want this object to be put on the scoping stack, because
864
- # that could create an infinite loop where we call an @association
865
- # method, which gets the current scope, which is this object, which
866
- # delegates to @association, and so on.
867
- def scoping
868
- @association.scope.scoping { yield }
869
- end
870
-
871
928
  # Returns a <tt>Relation</tt> object for the records in this association
872
929
  def scope
873
- @association.scope
930
+ @scope ||= @association.scope
874
931
  end
875
- alias spawn scope
876
932
 
877
933
  # Equivalent to <tt>Array#==</tt>. Returns +true+ if the two arrays
878
934
  # contain the same number of elements and if each element is equal
@@ -902,6 +958,12 @@ module ActiveRecord
902
958
  load_target == other
903
959
  end
904
960
 
961
+ ##
962
+ # :method: to_ary
963
+ #
964
+ # :call-seq:
965
+ # to_ary()
966
+ #
905
967
  # Returns a new array of objects from the collection. If the collection
906
968
  # hasn't been loaded, it fetches the records from the database.
907
969
  #
@@ -935,14 +997,15 @@ module ActiveRecord
935
997
  # # #<Pet id: 5, name: "Brain", person_id: 1>,
936
998
  # # #<Pet id: 6, name: "Boss", person_id: 1>
937
999
  # # ]
938
- def to_ary
939
- load_target.dup
1000
+
1001
+ def records # :nodoc:
1002
+ load_target
940
1003
  end
941
- alias_method :to_a, :to_ary
942
1004
 
943
1005
  # Adds one or more +records+ to the collection by setting their foreign keys
944
- # to the association's primary key. Returns +self+, so several appends may be
945
- # 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.
946
1009
  #
947
1010
  # class Person < ActiveRecord::Base
948
1011
  # has_many :pets
@@ -965,21 +1028,24 @@ module ActiveRecord
965
1028
  end
966
1029
  alias_method :push, :<<
967
1030
  alias_method :append, :<<
1031
+ alias_method :concat, :<<
968
1032
 
969
- def prepend(*args)
970
- 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"
971
1035
  end
972
1036
 
973
1037
  # Equivalent to +delete_all+. The difference is that returns +self+, instead
974
1038
  # of an array with the deleted objects, so methods can be chained. See
975
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.
976
1043
  def clear
977
1044
  delete_all
978
1045
  self
979
1046
  end
980
1047
 
981
1048
  # Reloads the collection from the database. Returns +self+.
982
- # Equivalent to <tt>collection(true)</tt>.
983
1049
  #
984
1050
  # class Person < ActiveRecord::Base
985
1051
  # has_many :pets
@@ -993,12 +1059,9 @@ module ActiveRecord
993
1059
  #
994
1060
  # person.pets.reload # fetches pets from the database
995
1061
  # # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
996
- #
997
- # person.pets(true) # fetches pets from the database
998
- # # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
999
1062
  def reload
1000
- proxy_association.reload
1001
- self
1063
+ proxy_association.reload(true)
1064
+ reset_scope
1002
1065
  end
1003
1066
 
1004
1067
  # Unloads the association. Returns +self+.
@@ -1020,8 +1083,46 @@ module ActiveRecord
1020
1083
  def reset
1021
1084
  proxy_association.reset
1022
1085
  proxy_association.reset_scope
1086
+ reset_scope
1087
+ end
1088
+
1089
+ def reset_scope # :nodoc:
1090
+ @offsets = {}
1091
+ @scope = nil
1023
1092
  self
1024
1093
  end
1094
+
1095
+ delegate_methods = [
1096
+ QueryMethods,
1097
+ SpawnMethods,
1098
+ ].flat_map { |klass|
1099
+ klass.public_instance_methods(false)
1100
+ } - self.public_instance_methods(false) - [:select] + [:scoping, :values]
1101
+
1102
+ delegate(*delegate_methods, to: :scope)
1103
+
1104
+ private
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
1025
1126
  end
1026
1127
  end
1027
1128
  end