activerecord 5.0.7.2 → 6.1.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 (363) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +829 -2015
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +11 -9
  5. data/examples/performance.rb +31 -29
  6. data/examples/simple.rb +5 -3
  7. data/lib/active_record.rb +37 -29
  8. data/lib/active_record/aggregations.rb +249 -247
  9. data/lib/active_record/association_relation.rb +30 -18
  10. data/lib/active_record/associations.rb +1714 -1596
  11. data/lib/active_record/associations/alias_tracker.rb +36 -42
  12. data/lib/active_record/associations/association.rb +143 -68
  13. data/lib/active_record/associations/association_scope.rb +98 -94
  14. data/lib/active_record/associations/belongs_to_association.rb +76 -46
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
  16. data/lib/active_record/associations/builder/association.rb +27 -28
  17. data/lib/active_record/associations/builder/belongs_to.rb +52 -60
  18. data/lib/active_record/associations/builder/collection_association.rb +12 -22
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +40 -62
  20. data/lib/active_record/associations/builder/has_many.rb +10 -2
  21. data/lib/active_record/associations/builder/has_one.rb +35 -2
  22. data/lib/active_record/associations/builder/singular_association.rb +5 -1
  23. data/lib/active_record/associations/collection_association.rb +104 -259
  24. data/lib/active_record/associations/collection_proxy.rb +169 -125
  25. data/lib/active_record/associations/foreign_association.rb +22 -0
  26. data/lib/active_record/associations/has_many_association.rb +46 -31
  27. data/lib/active_record/associations/has_many_through_association.rb +66 -46
  28. data/lib/active_record/associations/has_one_association.rb +71 -52
  29. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  30. data/lib/active_record/associations/join_dependency.rb +169 -180
  31. data/lib/active_record/associations/join_dependency/join_association.rb +53 -79
  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 +97 -104
  35. data/lib/active_record/associations/preloader/association.rb +109 -97
  36. data/lib/active_record/associations/preloader/through_association.rb +77 -76
  37. data/lib/active_record/associations/singular_association.rb +12 -45
  38. data/lib/active_record/associations/through_association.rb +27 -15
  39. data/lib/active_record/attribute_assignment.rb +55 -60
  40. data/lib/active_record/attribute_methods.rb +111 -141
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +17 -9
  42. data/lib/active_record/attribute_methods/dirty.rb +172 -112
  43. data/lib/active_record/attribute_methods/primary_key.rb +88 -91
  44. data/lib/active_record/attribute_methods/query.rb +6 -8
  45. data/lib/active_record/attribute_methods/read.rb +18 -50
  46. data/lib/active_record/attribute_methods/serialization.rb +38 -10
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +38 -66
  48. data/lib/active_record/attribute_methods/write.rb +25 -32
  49. data/lib/active_record/attributes.rb +69 -31
  50. data/lib/active_record/autosave_association.rb +102 -66
  51. data/lib/active_record/base.rb +16 -25
  52. data/lib/active_record/callbacks.rb +202 -43
  53. data/lib/active_record/coders/json.rb +2 -0
  54. data/lib/active_record/coders/yaml_column.rb +11 -12
  55. data/lib/active_record/connection_adapters.rb +50 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +661 -375
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +14 -38
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +269 -105
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +54 -35
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +137 -93
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +155 -113
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +328 -162
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +591 -259
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +229 -91
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +392 -244
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +457 -582
  69. data/lib/active_record/connection_adapters/column.rb +55 -13
  70. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  71. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +135 -49
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -23
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +79 -49
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +66 -56
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +20 -12
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +74 -37
  82. data/lib/active_record/connection_adapters/pool_config.rb +63 -0
  83. data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
  84. data/lib/active_record/connection_adapters/postgresql/column.rb +39 -28
  85. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +70 -101
  86. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
  87. data/lib/active_record/connection_adapters/postgresql/oid.rb +26 -21
  88. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -11
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
  90. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -6
  93. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +14 -4
  95. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  96. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
  97. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -18
  98. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  101. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
  104. data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +30 -9
  106. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -30
  107. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  108. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  109. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
  110. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  111. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  112. data/lib/active_record/connection_adapters/postgresql/quoting.rb +98 -38
  113. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +21 -27
  114. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
  115. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
  116. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +34 -32
  117. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +426 -324
  118. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +32 -23
  119. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -6
  120. data/lib/active_record/connection_adapters/postgresql_adapter.rb +418 -293
  121. data/lib/active_record/connection_adapters/schema_cache.rb +135 -18
  122. data/lib/active_record/connection_adapters/sql_type_metadata.rb +22 -7
  123. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
  124. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
  125. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +72 -18
  126. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -6
  127. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  128. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  129. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
  130. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +282 -290
  131. data/lib/active_record/connection_adapters/statement_pool.rb +9 -8
  132. data/lib/active_record/connection_handling.rb +287 -45
  133. data/lib/active_record/core.rb +385 -181
  134. data/lib/active_record/counter_cache.rb +60 -28
  135. data/lib/active_record/database_configurations.rb +272 -0
  136. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  137. data/lib/active_record/database_configurations/database_config.rb +80 -0
  138. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  139. data/lib/active_record/database_configurations/url_config.rb +53 -0
  140. data/lib/active_record/delegated_type.rb +209 -0
  141. data/lib/active_record/destroy_association_async_job.rb +36 -0
  142. data/lib/active_record/dynamic_matchers.rb +87 -87
  143. data/lib/active_record/enum.rb +122 -47
  144. data/lib/active_record/errors.rb +153 -22
  145. data/lib/active_record/explain.rb +13 -8
  146. data/lib/active_record/explain_registry.rb +3 -1
  147. data/lib/active_record/explain_subscriber.rb +9 -4
  148. data/lib/active_record/fixture_set/file.rb +20 -22
  149. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  150. data/lib/active_record/fixture_set/render_context.rb +17 -0
  151. data/lib/active_record/fixture_set/table_row.rb +152 -0
  152. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  153. data/lib/active_record/fixtures.rb +246 -507
  154. data/lib/active_record/gem_version.rb +6 -4
  155. data/lib/active_record/inheritance.rb +168 -95
  156. data/lib/active_record/insert_all.rb +208 -0
  157. data/lib/active_record/integration.rb +114 -25
  158. data/lib/active_record/internal_metadata.rb +30 -24
  159. data/lib/active_record/legacy_yaml_adapter.rb +11 -5
  160. data/lib/active_record/locking/optimistic.rb +81 -85
  161. data/lib/active_record/locking/pessimistic.rb +22 -6
  162. data/lib/active_record/log_subscriber.rb +68 -31
  163. data/lib/active_record/middleware/database_selector.rb +77 -0
  164. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  165. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  166. data/lib/active_record/migration.rb +439 -342
  167. data/lib/active_record/migration/command_recorder.rb +152 -98
  168. data/lib/active_record/migration/compatibility.rb +229 -60
  169. data/lib/active_record/migration/join_table.rb +8 -7
  170. data/lib/active_record/model_schema.rb +230 -122
  171. data/lib/active_record/nested_attributes.rb +213 -203
  172. data/lib/active_record/no_touching.rb +11 -2
  173. data/lib/active_record/null_relation.rb +12 -34
  174. data/lib/active_record/persistence.rb +471 -97
  175. data/lib/active_record/query_cache.rb +23 -12
  176. data/lib/active_record/querying.rb +43 -25
  177. data/lib/active_record/railtie.rb +155 -43
  178. data/lib/active_record/railties/console_sandbox.rb +2 -0
  179. data/lib/active_record/railties/controller_runtime.rb +34 -33
  180. data/lib/active_record/railties/databases.rake +507 -195
  181. data/lib/active_record/readonly_attributes.rb +9 -4
  182. data/lib/active_record/reflection.rb +245 -269
  183. data/lib/active_record/relation.rb +475 -324
  184. data/lib/active_record/relation/batches.rb +125 -72
  185. data/lib/active_record/relation/batches/batch_enumerator.rb +28 -10
  186. data/lib/active_record/relation/calculations.rb +267 -171
  187. data/lib/active_record/relation/delegation.rb +73 -69
  188. data/lib/active_record/relation/finder_methods.rb +238 -248
  189. data/lib/active_record/relation/from_clause.rb +7 -9
  190. data/lib/active_record/relation/merger.rb +95 -77
  191. data/lib/active_record/relation/predicate_builder.rb +109 -110
  192. data/lib/active_record/relation/predicate_builder/array_handler.rb +22 -17
  193. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
  194. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
  195. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +55 -0
  196. data/lib/active_record/relation/predicate_builder/range_handler.rb +7 -18
  197. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  198. data/lib/active_record/relation/query_attribute.rb +33 -2
  199. data/lib/active_record/relation/query_methods.rb +654 -374
  200. data/lib/active_record/relation/record_fetch_warning.rb +8 -6
  201. data/lib/active_record/relation/spawn_methods.rb +15 -14
  202. data/lib/active_record/relation/where_clause.rb +171 -109
  203. data/lib/active_record/result.rb +88 -51
  204. data/lib/active_record/runtime_registry.rb +5 -3
  205. data/lib/active_record/sanitization.rb +73 -100
  206. data/lib/active_record/schema.rb +7 -14
  207. data/lib/active_record/schema_dumper.rb +101 -69
  208. data/lib/active_record/schema_migration.rb +16 -12
  209. data/lib/active_record/scoping.rb +20 -20
  210. data/lib/active_record/scoping/default.rb +92 -95
  211. data/lib/active_record/scoping/named.rb +39 -30
  212. data/lib/active_record/secure_token.rb +19 -9
  213. data/lib/active_record/serialization.rb +7 -3
  214. data/lib/active_record/signed_id.rb +116 -0
  215. data/lib/active_record/statement_cache.rb +80 -29
  216. data/lib/active_record/store.rb +122 -42
  217. data/lib/active_record/suppressor.rb +6 -3
  218. data/lib/active_record/table_metadata.rb +51 -39
  219. data/lib/active_record/tasks/database_tasks.rb +332 -115
  220. data/lib/active_record/tasks/mysql_database_tasks.rb +66 -104
  221. data/lib/active_record/tasks/postgresql_database_tasks.rb +84 -56
  222. data/lib/active_record/tasks/sqlite_database_tasks.rb +40 -19
  223. data/lib/active_record/test_databases.rb +24 -0
  224. data/lib/active_record/test_fixtures.rb +246 -0
  225. data/lib/active_record/timestamp.rb +70 -38
  226. data/lib/active_record/touch_later.rb +26 -24
  227. data/lib/active_record/transactions.rb +121 -184
  228. data/lib/active_record/translation.rb +3 -1
  229. data/lib/active_record/type.rb +29 -17
  230. data/lib/active_record/type/adapter_specific_registry.rb +44 -48
  231. data/lib/active_record/type/date.rb +2 -0
  232. data/lib/active_record/type/date_time.rb +2 -0
  233. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  234. data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
  235. data/lib/active_record/type/internal/timezone.rb +2 -0
  236. data/lib/active_record/type/json.rb +30 -0
  237. data/lib/active_record/type/serialized.rb +20 -9
  238. data/lib/active_record/type/text.rb +11 -0
  239. data/lib/active_record/type/time.rb +12 -1
  240. data/lib/active_record/type/type_map.rb +14 -17
  241. data/lib/active_record/type/unsigned_integer.rb +16 -0
  242. data/lib/active_record/type_caster.rb +4 -2
  243. data/lib/active_record/type_caster/connection.rb +17 -13
  244. data/lib/active_record/type_caster/map.rb +10 -6
  245. data/lib/active_record/validations.rb +8 -5
  246. data/lib/active_record/validations/absence.rb +2 -0
  247. data/lib/active_record/validations/associated.rb +4 -3
  248. data/lib/active_record/validations/length.rb +2 -0
  249. data/lib/active_record/validations/numericality.rb +35 -0
  250. data/lib/active_record/validations/presence.rb +4 -2
  251. data/lib/active_record/validations/uniqueness.rb +52 -45
  252. data/lib/active_record/version.rb +3 -1
  253. data/lib/arel.rb +54 -0
  254. data/lib/arel/alias_predication.rb +9 -0
  255. data/lib/arel/attributes/attribute.rb +41 -0
  256. data/lib/arel/collectors/bind.rb +29 -0
  257. data/lib/arel/collectors/composite.rb +39 -0
  258. data/lib/arel/collectors/plain_string.rb +20 -0
  259. data/lib/arel/collectors/sql_string.rb +27 -0
  260. data/lib/arel/collectors/substitute_binds.rb +35 -0
  261. data/lib/arel/crud.rb +42 -0
  262. data/lib/arel/delete_manager.rb +18 -0
  263. data/lib/arel/errors.rb +9 -0
  264. data/lib/arel/expressions.rb +29 -0
  265. data/lib/arel/factory_methods.rb +49 -0
  266. data/lib/arel/insert_manager.rb +49 -0
  267. data/lib/arel/math.rb +45 -0
  268. data/lib/arel/nodes.rb +70 -0
  269. data/lib/arel/nodes/and.rb +32 -0
  270. data/lib/arel/nodes/ascending.rb +23 -0
  271. data/lib/arel/nodes/binary.rb +126 -0
  272. data/lib/arel/nodes/bind_param.rb +44 -0
  273. data/lib/arel/nodes/case.rb +55 -0
  274. data/lib/arel/nodes/casted.rb +62 -0
  275. data/lib/arel/nodes/comment.rb +29 -0
  276. data/lib/arel/nodes/count.rb +12 -0
  277. data/lib/arel/nodes/delete_statement.rb +45 -0
  278. data/lib/arel/nodes/descending.rb +23 -0
  279. data/lib/arel/nodes/equality.rb +15 -0
  280. data/lib/arel/nodes/extract.rb +24 -0
  281. data/lib/arel/nodes/false.rb +16 -0
  282. data/lib/arel/nodes/full_outer_join.rb +8 -0
  283. data/lib/arel/nodes/function.rb +44 -0
  284. data/lib/arel/nodes/grouping.rb +11 -0
  285. data/lib/arel/nodes/homogeneous_in.rb +72 -0
  286. data/lib/arel/nodes/in.rb +15 -0
  287. data/lib/arel/nodes/infix_operation.rb +92 -0
  288. data/lib/arel/nodes/inner_join.rb +8 -0
  289. data/lib/arel/nodes/insert_statement.rb +37 -0
  290. data/lib/arel/nodes/join_source.rb +20 -0
  291. data/lib/arel/nodes/matches.rb +18 -0
  292. data/lib/arel/nodes/named_function.rb +23 -0
  293. data/lib/arel/nodes/node.rb +51 -0
  294. data/lib/arel/nodes/node_expression.rb +13 -0
  295. data/lib/arel/nodes/ordering.rb +27 -0
  296. data/lib/arel/nodes/outer_join.rb +8 -0
  297. data/lib/arel/nodes/over.rb +15 -0
  298. data/lib/arel/nodes/regexp.rb +16 -0
  299. data/lib/arel/nodes/right_outer_join.rb +8 -0
  300. data/lib/arel/nodes/select_core.rb +67 -0
  301. data/lib/arel/nodes/select_statement.rb +41 -0
  302. data/lib/arel/nodes/sql_literal.rb +19 -0
  303. data/lib/arel/nodes/string_join.rb +11 -0
  304. data/lib/arel/nodes/table_alias.rb +31 -0
  305. data/lib/arel/nodes/terminal.rb +16 -0
  306. data/lib/arel/nodes/true.rb +16 -0
  307. data/lib/arel/nodes/unary.rb +44 -0
  308. data/lib/arel/nodes/unary_operation.rb +20 -0
  309. data/lib/arel/nodes/unqualified_column.rb +22 -0
  310. data/lib/arel/nodes/update_statement.rb +41 -0
  311. data/lib/arel/nodes/values_list.rb +9 -0
  312. data/lib/arel/nodes/window.rb +126 -0
  313. data/lib/arel/nodes/with.rb +11 -0
  314. data/lib/arel/order_predications.rb +13 -0
  315. data/lib/arel/predications.rb +250 -0
  316. data/lib/arel/select_manager.rb +270 -0
  317. data/lib/arel/table.rb +118 -0
  318. data/lib/arel/tree_manager.rb +72 -0
  319. data/lib/arel/update_manager.rb +34 -0
  320. data/lib/arel/visitors.rb +13 -0
  321. data/lib/arel/visitors/dot.rb +308 -0
  322. data/lib/arel/visitors/mysql.rb +93 -0
  323. data/lib/arel/visitors/postgresql.rb +120 -0
  324. data/lib/arel/visitors/sqlite.rb +38 -0
  325. data/lib/arel/visitors/to_sql.rb +899 -0
  326. data/lib/arel/visitors/visitor.rb +45 -0
  327. data/lib/arel/window_predications.rb +9 -0
  328. data/lib/rails/generators/active_record.rb +7 -5
  329. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  330. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  331. data/lib/rails/generators/active_record/migration.rb +22 -3
  332. data/lib/rails/generators/active_record/migration/migration_generator.rb +38 -35
  333. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +3 -1
  334. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +7 -5
  335. data/lib/rails/generators/active_record/model/model_generator.rb +41 -25
  336. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  337. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
  338. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  339. metadata +141 -57
  340. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  341. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  342. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  343. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  344. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  345. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  346. data/lib/active_record/associations/preloader/singular_association.rb +0 -20
  347. data/lib/active_record/attribute.rb +0 -213
  348. data/lib/active_record/attribute/user_provided_default.rb +0 -28
  349. data/lib/active_record/attribute_decorators.rb +0 -67
  350. data/lib/active_record/attribute_mutation_tracker.rb +0 -70
  351. data/lib/active_record/attribute_set.rb +0 -110
  352. data/lib/active_record/attribute_set/builder.rb +0 -132
  353. data/lib/active_record/collection_cache_key.rb +0 -50
  354. data/lib/active_record/connection_adapters/connection_specification.rb +0 -263
  355. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -22
  356. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +0 -50
  357. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  358. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  359. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -17
  360. data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
  361. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
  362. data/lib/active_record/relation/where_clause_factory.rb +0 -38
  363. data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -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,23 +13,23 @@ 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
- def initialize(klass, association) #:nodoc:
30
+ def initialize(klass, association, **) #:nodoc:
32
31
  @association = association
33
- super klass, klass.arel_table, klass.predicate_builder
32
+ super klass
34
33
 
35
34
  extensions = association.extensions
36
35
  extend(*extensions) if extensions.any?
@@ -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">,
@@ -95,20 +101,11 @@ module ActiveRecord
95
101
  # converting them into an array and iterating through them using
96
102
  # Array#select.
97
103
  #
98
- # person.pets.select { |pet| pet.name =~ /oo/ }
104
+ # person.pets.select { |pet| /oo/.match?(pet.name) }
99
105
  # # => [
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
111
  # rules as ActiveRecord::Base.find. Returns ActiveRecord::RecordNotFound
@@ -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,45 +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
 
174
+ ##
175
+ # :method: second
176
+ #
177
+ # :call-seq:
178
+ # second()
179
+ #
173
180
  # Same as #first except returns only the second record.
174
- def second(*args)
175
- @association.second(*args)
176
- end
177
181
 
182
+ ##
183
+ # :method: third
184
+ #
185
+ # :call-seq:
186
+ # third()
187
+ #
178
188
  # Same as #first except returns only the third record.
179
- def third(*args)
180
- @association.third(*args)
181
- end
182
189
 
190
+ ##
191
+ # :method: fourth
192
+ #
193
+ # :call-seq:
194
+ # fourth()
195
+ #
183
196
  # Same as #first except returns only the fourth record.
184
- def fourth(*args)
185
- @association.fourth(*args)
186
- end
187
197
 
198
+ ##
199
+ # :method: fifth
200
+ #
201
+ # :call-seq:
202
+ # fifth()
203
+ #
188
204
  # Same as #first except returns only the fifth record.
189
- def fifth(*args)
190
- @association.fifth(*args)
191
- end
192
205
 
206
+ ##
207
+ # :method: forty_two
208
+ #
209
+ # :call-seq:
210
+ # forty_two()
211
+ #
193
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
198
214
 
215
+ ##
216
+ # :method: third_to_last
217
+ #
218
+ # :call-seq:
219
+ # third_to_last()
220
+ #
199
221
  # Same as #first except returns only the third-to-last record.
200
- def third_to_last(*args)
201
- @association.third_to_last(*args)
202
- end
203
222
 
223
+ ##
224
+ # :method: second_to_last
225
+ #
226
+ # :call-seq:
227
+ # second_to_last()
228
+ #
204
229
  # Same as #first except returns only the second-to-last record.
205
- def second_to_last(*args)
206
- @association.second_to_last(*args)
207
- end
208
230
 
209
231
  # Returns the last record, or the last +n+ records, from the collection.
210
232
  # If the collection is empty, the first form returns +nil+, and the second
@@ -232,8 +254,9 @@ module ActiveRecord
232
254
  # another_person_without.pets # => []
233
255
  # another_person_without.pets.last # => nil
234
256
  # another_person_without.pets.last(3) # => []
235
- def last(*args)
236
- @association.last(*args)
257
+ def last(limit = nil)
258
+ load_target if find_from_target?
259
+ super
237
260
  end
238
261
 
239
262
  # Gives a record (or N records if a parameter is supplied) from the collection
@@ -261,8 +284,9 @@ module ActiveRecord
261
284
  # another_person_without.pets # => []
262
285
  # another_person_without.pets.take # => nil
263
286
  # another_person_without.pets.take(2) # => []
264
- def take(n = nil)
265
- @association.take(n)
287
+ def take(limit = nil)
288
+ load_target if find_from_target?
289
+ super
266
290
  end
267
291
 
268
292
  # Returns a new object of the collection type that has been instantiated
@@ -340,34 +364,6 @@ module ActiveRecord
340
364
  @association.create!(attributes, &block)
341
365
  end
342
366
 
343
- # Add one or more records to the collection by setting their foreign keys
344
- # to the association's primary key. Since #<< flattens its argument list and
345
- # inserts each record, +push+ and #concat behave identically. Returns +self+
346
- # so method calls may be chained.
347
- #
348
- # class Person < ActiveRecord::Base
349
- # has_many :pets
350
- # end
351
- #
352
- # person.pets.size # => 0
353
- # person.pets.concat(Pet.new(name: 'Fancy-Fancy'))
354
- # person.pets.concat(Pet.new(name: 'Spook'), Pet.new(name: 'Choo-Choo'))
355
- # person.pets.size # => 3
356
- #
357
- # person.id # => 1
358
- # person.pets
359
- # # => [
360
- # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
361
- # # #<Pet id: 2, name: "Spook", person_id: 1>,
362
- # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
363
- # # ]
364
- #
365
- # person.pets.concat([Pet.new(name: 'Brain'), Pet.new(name: 'Benny')])
366
- # person.pets.size # => 5
367
- def concat(*records)
368
- @association.concat(*records)
369
- end
370
-
371
367
  # Replaces this collection with +other_array+. This will perform a diff
372
368
  # and delete/add only records that have changed.
373
369
  #
@@ -378,7 +374,7 @@ module ActiveRecord
378
374
  # person.pets
379
375
  # # => [#<Pet id: 1, name: "Gorby", group: "cats", person_id: 1>]
380
376
  #
381
- # other_pets = [Pet.new(name: 'Puff', group: 'celebrities']
377
+ # other_pets = [Pet.new(name: 'Puff', group: 'celebrities')]
382
378
  #
383
379
  # person.pets.replace(other_pets)
384
380
  #
@@ -474,7 +470,7 @@ module ActiveRecord
474
470
  # Pet.find(1, 2, 3)
475
471
  # # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
476
472
  def delete_all(dependent = nil)
477
- @association.delete_all(dependent)
473
+ @association.delete_all(dependent).tap { reset_scope }
478
474
  end
479
475
 
480
476
  # Deletes the records of the collection directly from the database
@@ -501,7 +497,7 @@ module ActiveRecord
501
497
  #
502
498
  # Pet.find(1) # => Couldn't find Pet with id=1
503
499
  def destroy_all
504
- @association.destroy_all
500
+ @association.destroy_all.tap { reset_scope }
505
501
  end
506
502
 
507
503
  # Deletes the +records+ supplied from the collection according to the strategy
@@ -620,7 +616,7 @@ module ActiveRecord
620
616
  # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
621
617
  # # ]
622
618
  def delete(*records)
623
- @association.delete(*records)
619
+ @association.delete(*records).tap { reset_scope }
624
620
  end
625
621
 
626
622
  # Destroys the +records+ supplied and removes them from the collection.
@@ -692,9 +688,15 @@ module ActiveRecord
692
688
  #
693
689
  # Pet.find(4, 5, 6) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (4, 5, 6)
694
690
  def destroy(*records)
695
- @association.destroy(*records)
691
+ @association.destroy(*records).tap { reset_scope }
696
692
  end
697
693
 
694
+ ##
695
+ # :method: distinct
696
+ #
697
+ # :call-seq:
698
+ # distinct(value = true)
699
+ #
698
700
  # Specifies whether the records should be unique or not.
699
701
  #
700
702
  # class Person < ActiveRecord::Base
@@ -709,17 +711,35 @@ module ActiveRecord
709
711
  #
710
712
  # person.pets.select(:name).distinct
711
713
  # # => [#<Pet name: "Fancy-Fancy">]
712
- def distinct
713
- @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
714
724
  end
715
- alias uniq distinct
716
725
 
717
- # Count all records using SQL.
726
+ def pluck(*column_names)
727
+ null_scope? ? scope.pluck(*column_names) : super
728
+ end
729
+
730
+ ##
731
+ # :method: count
732
+ #
733
+ # :call-seq:
734
+ # count(column_name = nil, &block)
735
+ #
736
+ # Count all records.
718
737
  #
719
738
  # class Person < ActiveRecord::Base
720
739
  # has_many :pets
721
740
  # end
722
741
  #
742
+ # # This will perform the count using SQL.
723
743
  # person.pets.count # => 3
724
744
  # person.pets
725
745
  # # => [
@@ -727,17 +747,11 @@ module ActiveRecord
727
747
  # # #<Pet id: 2, name: "Spook", person_id: 1>,
728
748
  # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
729
749
  # # ]
730
- def count(column_name = nil)
731
- @association.count(column_name)
732
- end
733
-
734
- def calculate(operation, column_name)
735
- null_scope? ? scope.calculate(operation, column_name) : super
736
- end
737
-
738
- def pluck(*column_names)
739
- null_scope? ? scope.pluck(*column_names) : super
740
- 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
741
755
 
742
756
  # Returns the size of the collection. If the collection hasn't been loaded,
743
757
  # it executes a <tt>SELECT COUNT(*)</tt> query. Else it calls <tt>collection.size</tt>.
@@ -767,6 +781,12 @@ module ActiveRecord
767
781
  @association.size
768
782
  end
769
783
 
784
+ ##
785
+ # :method: length
786
+ #
787
+ # :call-seq:
788
+ # length()
789
+ #
770
790
  # Returns the size of the collection calling +size+ on the target.
771
791
  # If the collection has been already loaded, +length+ and +size+ are
772
792
  # equivalent. If not and you are going to need the records anyway this
@@ -787,9 +807,6 @@ module ActiveRecord
787
807
  # # #<Pet id: 2, name: "Spook", person_id: 1>,
788
808
  # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
789
809
  # # ]
790
- def length
791
- @association.length
792
- end
793
810
 
794
811
  # Returns +true+ if the collection is empty. If the collection has been
795
812
  # loaded it is equivalent
@@ -813,6 +830,12 @@ module ActiveRecord
813
830
  @association.empty?
814
831
  end
815
832
 
833
+ ##
834
+ # :method: any?
835
+ #
836
+ # :call-seq:
837
+ # any?()
838
+ #
816
839
  # Returns +true+ if the collection is not empty.
817
840
  #
818
841
  # class Person < ActiveRecord::Base
@@ -842,10 +865,13 @@ module ActiveRecord
842
865
  # pet.group == 'dogs'
843
866
  # end
844
867
  # # => true
845
- def any?(&block)
846
- @association.any?(&block)
847
- end
848
868
 
869
+ ##
870
+ # :method: many?
871
+ #
872
+ # :call-seq:
873
+ # many?()
874
+ #
849
875
  # Returns true if the collection has more than one record.
850
876
  # Equivalent to <tt>collection.size > 1</tt>.
851
877
  #
@@ -880,9 +906,6 @@ module ActiveRecord
880
906
  # pet.group == 'cats'
881
907
  # end
882
908
  # # => true
883
- def many?(&block)
884
- @association.many?(&block)
885
- end
886
909
 
887
910
  # Returns +true+ if the given +record+ is present in the collection.
888
911
  #
@@ -898,7 +921,7 @@ module ActiveRecord
898
921
  !!@association.include?(record)
899
922
  end
900
923
 
901
- def proxy_association
924
+ def proxy_association # :nodoc:
902
925
  @association
903
926
  end
904
927
 
@@ -935,6 +958,12 @@ module ActiveRecord
935
958
  load_target == other
936
959
  end
937
960
 
961
+ ##
962
+ # :method: to_ary
963
+ #
964
+ # :call-seq:
965
+ # to_ary()
966
+ #
938
967
  # Returns a new array of objects from the collection. If the collection
939
968
  # hasn't been loaded, it fetches the records from the database.
940
969
  #
@@ -968,18 +997,15 @@ module ActiveRecord
968
997
  # # #<Pet id: 5, name: "Brain", person_id: 1>,
969
998
  # # #<Pet id: 6, name: "Boss", person_id: 1>
970
999
  # # ]
971
- def to_ary
972
- load_target.dup
973
- end
974
- alias_method :to_a, :to_ary
975
1000
 
976
1001
  def records # :nodoc:
977
1002
  load_target
978
1003
  end
979
1004
 
980
1005
  # Adds one or more +records+ to the collection by setting their foreign keys
981
- # to the association's primary key. Returns +self+, so several appends may be
982
- # 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.
983
1009
  #
984
1010
  # class Person < ActiveRecord::Base
985
1011
  # has_many :pets
@@ -1002,8 +1028,9 @@ module ActiveRecord
1002
1028
  end
1003
1029
  alias_method :push, :<<
1004
1030
  alias_method :append, :<<
1031
+ alias_method :concat, :<<
1005
1032
 
1006
- def prepend(*args)
1033
+ def prepend(*args) # :nodoc:
1007
1034
  raise NoMethodError, "prepend on association is not defined. Please use <<, push or append"
1008
1035
  end
1009
1036
 
@@ -1019,7 +1046,6 @@ module ActiveRecord
1019
1046
  end
1020
1047
 
1021
1048
  # Reloads the collection from the database. Returns +self+.
1022
- # Equivalent to <tt>collection(true)</tt>.
1023
1049
  #
1024
1050
  # class Person < ActiveRecord::Base
1025
1051
  # has_many :pets
@@ -1033,11 +1059,8 @@ module ActiveRecord
1033
1059
  #
1034
1060
  # person.pets.reload # fetches pets from the database
1035
1061
  # # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
1036
- #
1037
- # person.pets(true) # fetches pets from the database
1038
- # # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
1039
1062
  def reload
1040
- proxy_association.reload
1063
+ proxy_association.reload(true)
1041
1064
  reset_scope
1042
1065
  end
1043
1066
 
@@ -1064,25 +1087,46 @@ module ActiveRecord
1064
1087
  end
1065
1088
 
1066
1089
  def reset_scope # :nodoc:
1090
+ @offsets = @take = nil
1067
1091
  @scope = nil
1068
1092
  self
1069
1093
  end
1070
1094
 
1095
+ def inspect # :nodoc:
1096
+ load_target if find_from_target?
1097
+ super
1098
+ end
1099
+
1071
1100
  delegate_methods = [
1072
1101
  QueryMethods,
1073
1102
  SpawnMethods,
1074
1103
  ].flat_map { |klass|
1075
1104
  klass.public_instance_methods(false)
1076
- } - self.public_instance_methods(false) + [:scoping]
1105
+ } - self.public_instance_methods(false) - [:select] + [
1106
+ :scoping, :values, :insert, :insert_all, :insert!, :insert_all!, :upsert, :upsert_all
1107
+ ]
1077
1108
 
1078
1109
  delegate(*delegate_methods, to: :scope)
1079
1110
 
1080
1111
  private
1112
+ def find_nth_with_limit(index, limit)
1113
+ load_target if find_from_target?
1114
+ super
1115
+ end
1116
+
1117
+ def find_nth_from_last(index)
1118
+ load_target if find_from_target?
1119
+ super
1120
+ end
1081
1121
 
1082
1122
  def null_scope?
1083
1123
  @association.null_scope?
1084
1124
  end
1085
1125
 
1126
+ def find_from_target?
1127
+ @association.find_from_target?
1128
+ end
1129
+
1086
1130
  def exec_queries
1087
1131
  load_target
1088
1132
  end