activerecord 5.0.7.2 → 6.0.3.4

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 (359) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +708 -2040
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +9 -7
  5. data/examples/performance.rb +31 -29
  6. data/examples/simple.rb +5 -3
  7. data/lib/active_record.rb +37 -22
  8. data/lib/active_record/advisory_lock_base.rb +18 -0
  9. data/lib/active_record/aggregations.rb +249 -247
  10. data/lib/active_record/association_relation.rb +18 -14
  11. data/lib/active_record/associations.rb +1603 -1592
  12. data/lib/active_record/associations/alias_tracker.rb +24 -34
  13. data/lib/active_record/associations/association.rb +114 -55
  14. data/lib/active_record/associations/association_scope.rb +94 -94
  15. data/lib/active_record/associations/belongs_to_association.rb +58 -42
  16. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
  17. data/lib/active_record/associations/builder/association.rb +18 -25
  18. data/lib/active_record/associations/builder/belongs_to.rb +43 -54
  19. data/lib/active_record/associations/builder/collection_association.rb +7 -18
  20. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +41 -62
  21. data/lib/active_record/associations/builder/has_many.rb +4 -0
  22. data/lib/active_record/associations/builder/has_one.rb +37 -1
  23. data/lib/active_record/associations/builder/singular_association.rb +4 -0
  24. data/lib/active_record/associations/collection_association.rb +86 -254
  25. data/lib/active_record/associations/collection_proxy.rb +158 -122
  26. data/lib/active_record/associations/foreign_association.rb +9 -0
  27. data/lib/active_record/associations/has_many_association.rb +23 -30
  28. data/lib/active_record/associations/has_many_through_association.rb +58 -44
  29. data/lib/active_record/associations/has_one_association.rb +59 -54
  30. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  31. data/lib/active_record/associations/join_dependency.rb +143 -176
  32. data/lib/active_record/associations/join_dependency/join_association.rb +38 -87
  33. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  34. data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
  35. data/lib/active_record/associations/preloader.rb +90 -103
  36. data/lib/active_record/associations/preloader/association.rb +86 -100
  37. data/lib/active_record/associations/preloader/through_association.rb +77 -76
  38. data/lib/active_record/associations/singular_association.rb +12 -45
  39. data/lib/active_record/associations/through_association.rb +26 -14
  40. data/lib/active_record/attribute_assignment.rb +54 -61
  41. data/lib/active_record/attribute_decorators.rb +38 -17
  42. data/lib/active_record/attribute_methods.rb +66 -106
  43. data/lib/active_record/attribute_methods/before_type_cast.rb +12 -8
  44. data/lib/active_record/attribute_methods/dirty.rb +179 -109
  45. data/lib/active_record/attribute_methods/primary_key.rb +85 -92
  46. data/lib/active_record/attribute_methods/query.rb +4 -3
  47. data/lib/active_record/attribute_methods/read.rb +20 -49
  48. data/lib/active_record/attribute_methods/serialization.rb +29 -7
  49. data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -66
  50. data/lib/active_record/attribute_methods/write.rb +34 -33
  51. data/lib/active_record/attributes.rb +38 -25
  52. data/lib/active_record/autosave_association.rb +54 -35
  53. data/lib/active_record/base.rb +27 -24
  54. data/lib/active_record/callbacks.rb +64 -35
  55. data/lib/active_record/coders/json.rb +2 -0
  56. data/lib/active_record/coders/yaml_column.rb +11 -12
  57. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +552 -323
  58. data/lib/active_record/connection_adapters/abstract/database_limits.rb +23 -5
  59. data/lib/active_record/connection_adapters/abstract/database_statements.rb +215 -94
  60. data/lib/active_record/connection_adapters/abstract/query_cache.rb +59 -35
  61. data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -75
  62. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +33 -28
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +228 -147
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +68 -80
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +400 -213
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +169 -79
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +367 -202
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +396 -562
  70. data/lib/active_record/connection_adapters/column.rb +41 -13
  71. data/lib/active_record/connection_adapters/connection_specification.rb +172 -139
  72. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +11 -4
  73. data/lib/active_record/connection_adapters/mysql/column.rb +8 -31
  74. data/lib/active_record/connection_adapters/mysql/database_statements.rb +137 -49
  75. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +24 -23
  76. data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -20
  77. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
  78. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +58 -56
  79. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +70 -36
  80. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
  81. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +12 -13
  82. data/lib/active_record/connection_adapters/mysql2_adapter.rb +48 -30
  83. data/lib/active_record/connection_adapters/postgresql/column.rb +19 -31
  84. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -54
  85. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +5 -3
  86. data/lib/active_record/connection_adapters/postgresql/oid.rb +24 -21
  87. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +22 -11
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +6 -5
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +4 -2
  94. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  95. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
  96. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +19 -18
  97. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  99. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -5
  101. data/lib/active_record/connection_adapters/postgresql/oid/{json.rb → oid.rb} +6 -1
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +30 -9
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +34 -31
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +8 -4
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  109. data/lib/active_record/connection_adapters/postgresql/quoting.rb +95 -35
  110. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +20 -26
  111. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +147 -105
  113. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +34 -32
  114. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +378 -308
  115. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +26 -25
  116. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -6
  117. data/lib/active_record/connection_adapters/postgresql_adapter.rb +383 -275
  118. data/lib/active_record/connection_adapters/schema_cache.rb +46 -12
  119. data/lib/active_record/connection_adapters/sql_type_metadata.rb +13 -8
  120. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -0
  121. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +3 -1
  122. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +72 -18
  123. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +3 -8
  124. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  126. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  127. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +259 -266
  128. data/lib/active_record/connection_adapters/statement_pool.rb +9 -8
  129. data/lib/active_record/connection_handling.rb +143 -40
  130. data/lib/active_record/core.rb +201 -163
  131. data/lib/active_record/counter_cache.rb +60 -28
  132. data/lib/active_record/database_configurations.rb +233 -0
  133. data/lib/active_record/database_configurations/database_config.rb +37 -0
  134. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  135. data/lib/active_record/database_configurations/url_config.rb +78 -0
  136. data/lib/active_record/define_callbacks.rb +22 -0
  137. data/lib/active_record/dynamic_matchers.rb +87 -87
  138. data/lib/active_record/enum.rb +60 -23
  139. data/lib/active_record/errors.rb +114 -18
  140. data/lib/active_record/explain.rb +4 -4
  141. data/lib/active_record/explain_registry.rb +3 -1
  142. data/lib/active_record/explain_subscriber.rb +9 -4
  143. data/lib/active_record/fixture_set/file.rb +13 -8
  144. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  145. data/lib/active_record/fixture_set/render_context.rb +17 -0
  146. data/lib/active_record/fixture_set/table_row.rb +152 -0
  147. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  148. data/lib/active_record/fixtures.rb +194 -504
  149. data/lib/active_record/gem_version.rb +5 -3
  150. data/lib/active_record/inheritance.rb +150 -99
  151. data/lib/active_record/insert_all.rb +179 -0
  152. data/lib/active_record/integration.rb +116 -25
  153. data/lib/active_record/internal_metadata.rb +16 -19
  154. data/lib/active_record/legacy_yaml_adapter.rb +4 -2
  155. data/lib/active_record/locking/optimistic.rb +77 -87
  156. data/lib/active_record/locking/pessimistic.rb +18 -6
  157. data/lib/active_record/log_subscriber.rb +48 -29
  158. data/lib/active_record/middleware/database_selector.rb +74 -0
  159. data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
  160. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  161. data/lib/active_record/migration.rb +369 -302
  162. data/lib/active_record/migration/command_recorder.rb +134 -100
  163. data/lib/active_record/migration/compatibility.rb +174 -56
  164. data/lib/active_record/migration/join_table.rb +8 -7
  165. data/lib/active_record/model_schema.rb +131 -127
  166. data/lib/active_record/nested_attributes.rb +213 -202
  167. data/lib/active_record/no_touching.rb +12 -3
  168. data/lib/active_record/null_relation.rb +12 -34
  169. data/lib/active_record/persistence.rb +446 -77
  170. data/lib/active_record/query_cache.rb +13 -12
  171. data/lib/active_record/querying.rb +37 -24
  172. data/lib/active_record/railtie.rb +128 -36
  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 +312 -177
  177. data/lib/active_record/readonly_attributes.rb +5 -4
  178. data/lib/active_record/reflection.rb +214 -252
  179. data/lib/active_record/relation.rb +440 -318
  180. data/lib/active_record/relation/batches.rb +98 -52
  181. data/lib/active_record/relation/batches/batch_enumerator.rb +3 -1
  182. data/lib/active_record/relation/calculations.rb +212 -173
  183. data/lib/active_record/relation/delegation.rb +72 -69
  184. data/lib/active_record/relation/finder_methods.rb +207 -247
  185. data/lib/active_record/relation/from_clause.rb +6 -8
  186. data/lib/active_record/relation/merger.rb +78 -62
  187. data/lib/active_record/relation/predicate_builder.rb +83 -105
  188. data/lib/active_record/relation/predicate_builder/array_handler.rb +20 -14
  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 +4 -3
  191. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +6 -4
  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 +7 -18
  194. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  195. data/lib/active_record/relation/query_attribute.rb +33 -2
  196. data/lib/active_record/relation/query_methods.rb +476 -334
  197. data/lib/active_record/relation/record_fetch_warning.rb +5 -3
  198. data/lib/active_record/relation/spawn_methods.rb +8 -8
  199. data/lib/active_record/relation/where_clause.rb +111 -96
  200. data/lib/active_record/relation/where_clause_factory.rb +6 -11
  201. data/lib/active_record/result.rb +69 -40
  202. data/lib/active_record/runtime_registry.rb +5 -3
  203. data/lib/active_record/sanitization.rb +83 -99
  204. data/lib/active_record/schema.rb +7 -14
  205. data/lib/active_record/schema_dumper.rb +71 -69
  206. data/lib/active_record/schema_migration.rb +16 -6
  207. data/lib/active_record/scoping.rb +20 -20
  208. data/lib/active_record/scoping/default.rb +92 -95
  209. data/lib/active_record/scoping/named.rb +47 -27
  210. data/lib/active_record/secure_token.rb +4 -2
  211. data/lib/active_record/serialization.rb +2 -0
  212. data/lib/active_record/statement_cache.rb +63 -28
  213. data/lib/active_record/store.rb +121 -41
  214. data/lib/active_record/suppressor.rb +6 -3
  215. data/lib/active_record/table_metadata.rb +39 -18
  216. data/lib/active_record/tasks/database_tasks.rb +271 -81
  217. data/lib/active_record/tasks/mysql_database_tasks.rb +54 -91
  218. data/lib/active_record/tasks/postgresql_database_tasks.rb +77 -47
  219. data/lib/active_record/tasks/sqlite_database_tasks.rb +33 -16
  220. data/lib/active_record/test_databases.rb +23 -0
  221. data/lib/active_record/test_fixtures.rb +225 -0
  222. data/lib/active_record/timestamp.rb +70 -36
  223. data/lib/active_record/touch_later.rb +8 -6
  224. data/lib/active_record/transactions.rb +141 -157
  225. data/lib/active_record/translation.rb +3 -1
  226. data/lib/active_record/type.rb +23 -18
  227. data/lib/active_record/type/adapter_specific_registry.rb +44 -48
  228. data/lib/active_record/type/date.rb +2 -0
  229. data/lib/active_record/type/date_time.rb +2 -0
  230. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  231. data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
  232. data/lib/active_record/type/internal/timezone.rb +2 -0
  233. data/lib/active_record/type/json.rb +30 -0
  234. data/lib/active_record/type/serialized.rb +16 -9
  235. data/lib/active_record/type/text.rb +11 -0
  236. data/lib/active_record/type/time.rb +2 -1
  237. data/lib/active_record/type/type_map.rb +14 -17
  238. data/lib/active_record/type/unsigned_integer.rb +16 -0
  239. data/lib/active_record/type_caster.rb +4 -2
  240. data/lib/active_record/type_caster/connection.rb +17 -12
  241. data/lib/active_record/type_caster/map.rb +5 -4
  242. data/lib/active_record/validations.rb +7 -5
  243. data/lib/active_record/validations/absence.rb +2 -0
  244. data/lib/active_record/validations/associated.rb +4 -3
  245. data/lib/active_record/validations/length.rb +2 -0
  246. data/lib/active_record/validations/presence.rb +4 -2
  247. data/lib/active_record/validations/uniqueness.rb +29 -42
  248. data/lib/active_record/version.rb +3 -1
  249. data/lib/arel.rb +62 -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 +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.rb +20 -0
  316. data/lib/arel/visitors/depth_first.rb +203 -0
  317. data/lib/arel/visitors/dot.rb +296 -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 +156 -0
  321. data/lib/arel/visitors/mysql.rb +83 -0
  322. data/lib/arel/visitors/oracle.rb +158 -0
  323. data/lib/arel/visitors/oracle12.rb +65 -0
  324. data/lib/arel/visitors/postgresql.rb +109 -0
  325. data/lib/arel/visitors/sqlite.rb +38 -0
  326. data/lib/arel/visitors/to_sql.rb +888 -0
  327. data/lib/arel/visitors/visitor.rb +45 -0
  328. data/lib/arel/visitors/where_sql.rb +22 -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 +26 -0
  332. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  333. data/lib/rails/generators/active_record/migration.rb +17 -3
  334. data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -35
  335. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +1 -1
  336. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +4 -2
  337. data/lib/rails/generators/active_record/model/model_generator.rb +9 -30
  338. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +10 -1
  339. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  340. metadata +137 -52
  341. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  342. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  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 -15
  346. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  347. data/lib/active_record/associations/preloader/singular_association.rb +0 -20
  348. data/lib/active_record/attribute.rb +0 -213
  349. data/lib/active_record/attribute/user_provided_default.rb +0 -28
  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/postgresql/oid/rails_5_1_point.rb +0 -50
  355. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  356. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  357. data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
  358. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -57
  359. data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,146 +1,132 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Associations
3
5
  class Preloader
4
6
  class Association #:nodoc:
5
- attr_reader :owners, :reflection, :preload_scope, :model, :klass
6
- attr_reader :preloaded_records
7
-
8
7
  def initialize(klass, owners, reflection, preload_scope)
9
8
  @klass = klass
10
9
  @owners = owners
11
10
  @reflection = reflection
12
11
  @preload_scope = preload_scope
13
12
  @model = owners.first && owners.first.class
14
- @scope = nil
15
- @preloaded_records = []
16
- end
17
-
18
- def run(preloader)
19
- preload(preloader)
20
- end
21
-
22
- def preload(preloader)
23
- raise NotImplementedError
24
- end
25
-
26
- def scope
27
- @scope ||= build_scope
28
- end
29
-
30
- def records_for(ids)
31
- query_scope(ids)
32
- end
33
-
34
- def query_scope(ids)
35
- scope.where(association_key_name => ids)
36
13
  end
37
14
 
38
- def table
39
- klass.arel_table
15
+ def run
16
+ if !preload_scope || preload_scope.empty_scope?
17
+ owners.each do |owner|
18
+ associate_records_to_owner(owner, records_by_owner[owner] || [])
19
+ end
20
+ else
21
+ # Custom preload scope is used and
22
+ # the association can not be marked as loaded
23
+ # Loading into a Hash instead
24
+ records_by_owner
25
+ end
26
+ self
40
27
  end
41
28
 
42
- # The name of the key on the associated records
43
- def association_key_name
44
- raise NotImplementedError
29
+ def records_by_owner
30
+ # owners can be duplicated when a relation has a collection association join
31
+ # #compare_by_identity makes such owners different hash keys
32
+ @records_by_owner ||= preloaded_records.each_with_object({}.compare_by_identity) do |record, result|
33
+ owners_by_key[convert_key(record[association_key_name])].each do |owner|
34
+ (result[owner] ||= []) << record
35
+ end
36
+ end
45
37
  end
46
38
 
47
- # This is overridden by HABTM as the condition should be on the foreign_key column in
48
- # the join table
49
- def association_key
50
- klass.arel_attribute(association_key_name, table)
39
+ def preloaded_records
40
+ return @preloaded_records if defined?(@preloaded_records)
41
+ @preloaded_records = owner_keys.empty? ? [] : records_for(owner_keys)
51
42
  end
52
43
 
53
- # The name of the key on the model which declares the association
54
- def owner_key_name
55
- raise NotImplementedError
56
- end
44
+ private
45
+ attr_reader :owners, :reflection, :preload_scope, :model, :klass
57
46
 
58
- def options
59
- reflection.options
60
- end
47
+ # The name of the key on the associated records
48
+ def association_key_name
49
+ reflection.join_primary_key(klass)
50
+ end
61
51
 
62
- private
52
+ # The name of the key on the model which declares the association
53
+ def owner_key_name
54
+ reflection.join_foreign_key
55
+ end
63
56
 
64
- def associated_records_by_owner(preloader)
65
- records = load_records do |record|
66
- owner = owners_by_key[convert_key(record[association_key_name])]
57
+ def associate_records_to_owner(owner, records)
67
58
  association = owner.association(reflection.name)
68
- association.set_inverse_instance(record)
59
+ if reflection.collection?
60
+ association.target = records
61
+ else
62
+ association.target = records.first
63
+ end
69
64
  end
70
65
 
71
- owners.each_with_object({}) do |owner, result|
72
- result[owner] = records[convert_key(owner[owner_key_name])] || []
66
+ def owner_keys
67
+ @owner_keys ||= owners_by_key.keys
73
68
  end
74
- end
75
69
 
76
- def owner_keys
77
- unless defined?(@owner_keys)
78
- @owner_keys = owners.map do |owner|
79
- owner[owner_key_name]
70
+ def owners_by_key
71
+ @owners_by_key ||= owners.each_with_object({}) do |owner, result|
72
+ key = convert_key(owner[owner_key_name])
73
+ (result[key] ||= []) << owner if key
80
74
  end
81
- @owner_keys.uniq!
82
- @owner_keys.compact!
83
75
  end
84
- @owner_keys
85
- end
86
76
 
87
- def owners_by_key
88
- unless defined?(@owners_by_key)
89
- @owners_by_key = owners.each_with_object({}) do |owner, h|
90
- h[convert_key(owner[owner_key_name])] = owner
77
+ def key_conversion_required?
78
+ unless defined?(@key_conversion_required)
79
+ @key_conversion_required = (association_key_type != owner_key_type)
91
80
  end
81
+
82
+ @key_conversion_required
92
83
  end
93
- @owners_by_key
94
- end
95
84
 
96
- def key_conversion_required?
97
- @key_conversion_required ||= association_key_type != owner_key_type
98
- end
85
+ def convert_key(key)
86
+ if key_conversion_required?
87
+ key.to_s
88
+ else
89
+ key
90
+ end
91
+ end
99
92
 
100
- def convert_key(key)
101
- if key_conversion_required?
102
- key.to_s
103
- else
104
- key
93
+ def association_key_type
94
+ @klass.type_for_attribute(association_key_name).type
105
95
  end
106
- end
107
96
 
108
- def association_key_type
109
- @klass.type_for_attribute(association_key_name.to_s).type
110
- end
97
+ def owner_key_type
98
+ @model.type_for_attribute(owner_key_name).type
99
+ end
111
100
 
112
- def owner_key_type
113
- @model.type_for_attribute(owner_key_name.to_s).type
114
- end
101
+ def records_for(ids)
102
+ scope.where(association_key_name => ids).load do |record|
103
+ # Processing only the first owner
104
+ # because the record is modified but not an owner
105
+ owner = owners_by_key[convert_key(record[association_key_name])].first
106
+ association = owner.association(reflection.name)
107
+ association.set_inverse_instance(record)
108
+ end
109
+ end
115
110
 
116
- def load_records(&block)
117
- return {} if owner_keys.empty?
118
- # Some databases impose a limit on the number of ids in a list (in Oracle it's 1000)
119
- # Make several smaller queries if necessary or make one query if the adapter supports it
120
- slices = owner_keys.each_slice(klass.connection.in_clause_length || owner_keys.size)
121
- @preloaded_records = slices.flat_map do |slice|
122
- records_for(slice).load(&block)
111
+ def scope
112
+ @scope ||= build_scope
123
113
  end
124
- @preloaded_records.group_by do |record|
125
- convert_key(record[association_key_name])
114
+
115
+ def reflection_scope
116
+ @reflection_scope ||= reflection.scope ? reflection.scope_for(klass.unscoped) : klass.unscoped
126
117
  end
127
- end
128
118
 
129
- def reflection_scope
130
- @reflection_scope ||= reflection.scope_for(klass)
131
- end
119
+ def build_scope
120
+ scope = klass.scope_for_association
132
121
 
133
- def build_scope
134
- scope = klass.scope_for_association
122
+ if reflection.type && !reflection.through_reflection?
123
+ scope.where!(reflection.type => model.polymorphic_name)
124
+ end
135
125
 
136
- if reflection.type
137
- scope.where!(reflection.type => model.base_class.sti_name)
126
+ scope.merge!(reflection_scope) if reflection.scope
127
+ scope.merge!(preload_scope) if preload_scope
128
+ scope
138
129
  end
139
-
140
- scope.merge!(reflection_scope)
141
- scope.merge!(preload_scope) if preload_scope != NULL_RELATION
142
- scope
143
- end
144
130
  end
145
131
  end
146
132
  end
@@ -1,114 +1,115 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Associations
3
5
  class Preloader
4
- module ThroughAssociation #:nodoc:
5
- def through_reflection
6
- reflection.through_reflection
6
+ class ThroughAssociation < Association # :nodoc:
7
+ PRELOADER = ActiveRecord::Associations::Preloader.new
8
+
9
+ def initialize(*)
10
+ super
11
+ @already_loaded = owners.first.association(through_reflection.name).loaded?
7
12
  end
8
13
 
9
- def source_reflection
10
- reflection.source_reflection
14
+ def preloaded_records
15
+ @preloaded_records ||= source_preloaders.flat_map(&:preloaded_records)
11
16
  end
12
17
 
13
- def associated_records_by_owner(preloader)
14
- preloader.preload(owners,
15
- through_reflection.name,
16
- through_scope)
18
+ def records_by_owner
19
+ return @records_by_owner if defined?(@records_by_owner)
20
+ source_records_by_owner = source_preloaders.map(&:records_by_owner).reduce(:merge)
21
+ through_records_by_owner = through_preloaders.map(&:records_by_owner).reduce(:merge)
17
22
 
18
- through_records = owners.map do |owner|
19
- association = owner.association through_reflection.name
23
+ @records_by_owner = owners.each_with_object({}) do |owner, result|
24
+ through_records = through_records_by_owner[owner] || []
20
25
 
21
- center = target_records_from_association(association)
22
- [owner, Array(center)]
23
- end
24
-
25
- reset_association owners, through_reflection.name
26
+ if @already_loaded
27
+ if source_type = reflection.options[:source_type]
28
+ through_records = through_records.select do |record|
29
+ record[reflection.foreign_type] == source_type
30
+ end
31
+ end
32
+ end
26
33
 
27
- middle_records = through_records.flat_map { |(_,rec)| rec }
34
+ records = through_records.flat_map do |record|
35
+ source_records_by_owner[record]
36
+ end
28
37
 
29
- preloaders = preloader.preload(middle_records,
30
- source_reflection.name,
31
- reflection_scope)
38
+ records.compact!
39
+ records.sort_by! { |rhs| preload_index[rhs] } if scope.order_values.any?
40
+ records.uniq! if scope.distinct_value
41
+ result[owner] = records
42
+ end
43
+ end
32
44
 
33
- @preloaded_records = preloaders.flat_map(&:preloaded_records)
45
+ private
46
+ def source_preloaders
47
+ @source_preloaders ||= PRELOADER.preload(middle_records, source_reflection.name, scope)
48
+ end
34
49
 
35
- middle_to_pl = preloaders.each_with_object({}) do |pl,h|
36
- pl.owners.each { |middle|
37
- h[middle] = pl
38
- }
50
+ def middle_records
51
+ through_preloaders.flat_map(&:preloaded_records)
39
52
  end
40
53
 
41
- through_records.each_with_object({}) do |(lhs,center), records_by_owner|
42
- pl_to_middle = center.group_by { |record| middle_to_pl[record] }
54
+ def through_preloaders
55
+ @through_preloaders ||= PRELOADER.preload(owners, through_reflection.name, through_scope)
56
+ end
43
57
 
44
- records_by_owner[lhs] = pl_to_middle.flat_map do |pl, middles|
45
- rhs_records = middles.flat_map { |r|
46
- association = r.association source_reflection.name
58
+ def through_reflection
59
+ reflection.through_reflection
60
+ end
47
61
 
48
- target_records_from_association(association)
49
- }.compact
62
+ def source_reflection
63
+ reflection.source_reflection
64
+ end
50
65
 
51
- # Respect the order on `reflection_scope` if it exists, else use the natural order.
52
- if reflection_scope.values[:order].present?
53
- @id_map ||= id_to_index_map @preloaded_records
54
- rhs_records.sort_by { |rhs| @id_map[rhs] }
55
- else
56
- rhs_records
57
- end
66
+ def preload_index
67
+ @preload_index ||= preloaded_records.each_with_object({}).with_index do |(record, result), index|
68
+ result[record] = index
58
69
  end
59
70
  end
60
- end
61
71
 
62
- private
72
+ def through_scope
73
+ scope = through_reflection.klass.unscoped
74
+ options = reflection.options
63
75
 
64
- def id_to_index_map(ids)
65
- id_map = {}
66
- ids.each_with_index { |id, index| id_map[id] = index }
67
- id_map
68
- end
76
+ values = reflection_scope.values
77
+ if annotations = values[:annotate]
78
+ scope.annotate!(*annotations)
79
+ end
69
80
 
70
- def reset_association(owners, association_name)
71
- should_reset = (through_scope != through_reflection.klass.unscoped) ||
72
- (reflection.options[:source_type] && through_reflection.collection?)
81
+ if options[:source_type]
82
+ scope.where! reflection.foreign_type => options[:source_type]
83
+ elsif !reflection_scope.where_clause.empty?
84
+ scope.where_clause = reflection_scope.where_clause
73
85
 
74
- # Don't cache the association - we would only be caching a subset
75
- if should_reset
76
- owners.each { |owner|
77
- owner.association(association_name).reset
78
- }
79
- end
80
- end
86
+ if includes = values[:includes]
87
+ scope.includes!(source_reflection.name => includes)
88
+ else
89
+ scope.includes!(source_reflection.name)
90
+ end
81
91
 
82
- def through_scope
83
- scope = through_reflection.klass.unscoped
84
- values = reflection_scope.values
92
+ if values[:references] && !values[:references].empty?
93
+ scope.references!(values[:references])
94
+ else
95
+ scope.references!(source_reflection.table_name)
96
+ end
85
97
 
86
- if options[:source_type]
87
- scope.where! reflection.foreign_type => options[:source_type]
88
- else
89
- unless reflection_scope.where_clause.empty?
90
- scope.includes_values = Array(values[:includes] || options[:source])
91
- scope.where_clause = reflection_scope.where_clause
92
98
  if joins = values[:joins]
93
99
  scope.joins!(source_reflection.name => joins)
94
100
  end
101
+
95
102
  if left_outer_joins = values[:left_outer_joins]
96
103
  scope.left_outer_joins!(source_reflection.name => left_outer_joins)
97
104
  end
98
- end
99
105
 
100
- scope.references! values[:references]
101
- if scope.eager_loading? && order_values = values[:order]
102
- scope = scope.order(order_values)
106
+ if scope.eager_loading? && order_values = values[:order]
107
+ scope = scope.order(order_values)
108
+ end
103
109
  end
104
- end
105
110
 
106
- scope
107
- end
108
-
109
- def target_records_from_association(association)
110
- association.loaded? ? association.target : association.reader
111
- end
111
+ scope
112
+ end
112
113
  end
113
114
  end
114
115
  end
@@ -1,16 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Associations
3
5
  class SingularAssociation < Association #:nodoc:
4
6
  # Implements the reader method, e.g. foo.bar for Foo.has_one :bar
5
- def reader(force_reload = false)
6
- if force_reload && klass
7
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
8
- Passing an argument to force an association to reload is now
9
- deprecated and will be removed in Rails 5.1. Please call `reload_#{reflection.name}` instead.
10
- MSG
11
-
12
- klass.uncached { reload }
13
- elsif !loaded? || stale_target?
7
+ def reader
8
+ if !loaded? || stale_target?
14
9
  reload
15
10
  end
16
11
 
@@ -22,17 +17,8 @@ module ActiveRecord
22
17
  replace(record)
23
18
  end
24
19
 
25
- def create(attributes = {}, &block)
26
- _create_record(attributes, &block)
27
- end
28
-
29
- def create!(attributes = {}, &block)
30
- _create_record(attributes, true, &block)
31
- end
32
-
33
- def build(attributes = {})
34
- record = build_record(attributes)
35
- yield(record) if block_given?
20
+ def build(attributes = {}, &block)
21
+ record = build_record(attributes, &block)
36
22
  set_new_record(record)
37
23
  record
38
24
  end
@@ -40,35 +26,17 @@ module ActiveRecord
40
26
  # Implements the reload reader method, e.g. foo.reload_bar for
41
27
  # Foo.has_one :bar
42
28
  def force_reload_reader
43
- klass.uncached { reload }
29
+ reload(true)
44
30
  target
45
31
  end
46
32
 
47
33
  private
48
-
49
- def create_scope
50
- scope.scope_for_create.stringify_keys.except(klass.primary_key)
51
- end
52
-
53
- def get_records
54
- return scope.limit(1).records if skip_statement_cache?
55
-
56
- conn = klass.connection
57
- sc = reflection.association_scope_cache(conn, owner) do
58
- StatementCache.create(conn) { |params|
59
- as = AssociationScope.create { params.bind }
60
- target_scope.merge(as.scope(self, conn)).limit(1)
61
- }
62
- end
63
-
64
- binds = AssociationScope.get_bind_values(owner, reflection.chain)
65
- sc.execute binds, klass, klass.connection
34
+ def scope_for_create
35
+ super.except!(klass.primary_key)
66
36
  end
67
37
 
68
38
  def find_target
69
- if record = get_records.first
70
- set_inverse_instance record
71
- end
39
+ super.first
72
40
  end
73
41
 
74
42
  def replace(record)
@@ -79,9 +47,8 @@ module ActiveRecord
79
47
  replace(record)
80
48
  end
81
49
 
82
- def _create_record(attributes, raise_error = false)
83
- record = build_record(attributes)
84
- yield(record) if block_given?
50
+ def _create_record(attributes, raise_error = false, &block)
51
+ record = build_record(attributes, &block)
85
52
  saved = record.save
86
53
  set_new_record(record)
87
54
  raise RecordInvalid.new(record) if !saved && raise_error