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,30 +1,39 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
- # = Active Record Has One Through Association
3
4
  module Associations
5
+ # = Active Record Has One Through Association
4
6
  class HasOneThroughAssociation < HasOneAssociation #:nodoc:
5
7
  include ThroughAssociation
6
8
 
7
- def replace(record)
8
- create_through_record(record)
9
- self.target = record
10
- end
11
-
12
9
  private
10
+ def replace(record, save = true)
11
+ create_through_record(record, save)
12
+ self.target = record
13
+ end
13
14
 
14
- def create_through_record(record)
15
+ def create_through_record(record, save)
15
16
  ensure_not_nested
16
17
 
17
- through_proxy = owner.association(through_reflection.name)
18
- through_record = through_proxy.send(:load_target)
18
+ through_proxy = through_association
19
+ through_record = through_proxy.load_target
19
20
 
20
21
  if through_record && !record
21
22
  through_record.destroy
22
23
  elsif record
23
24
  attributes = construct_join_attributes(record)
24
25
 
26
+ if through_record && through_record.destroyed?
27
+ through_record = through_proxy.tap(&:reload).target
28
+ end
29
+
25
30
  if through_record
26
- through_record.update(attributes)
27
- elsif owner.new_record?
31
+ if through_record.new_record?
32
+ through_record.assign_attributes(attributes)
33
+ else
34
+ through_record.update(attributes)
35
+ end
36
+ elsif owner.new_record? || !save
28
37
  through_proxy.build(attributes)
29
38
  else
30
39
  through_proxy.create(attributes)
@@ -1,21 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Associations
3
5
  class JoinDependency # :nodoc:
4
- autoload :JoinBase, 'active_record/associations/join_dependency/join_base'
5
- autoload :JoinAssociation, 'active_record/associations/join_dependency/join_association'
6
+ autoload :JoinBase, "active_record/associations/join_dependency/join_base"
7
+ autoload :JoinAssociation, "active_record/associations/join_dependency/join_association"
6
8
 
7
9
  class Aliases # :nodoc:
8
10
  def initialize(tables)
9
11
  @tables = tables
10
- @alias_cache = tables.each_with_object({}) { |table,h|
11
- h[table.node] = table.columns.each_with_object({}) { |column,i|
12
+ @alias_cache = tables.each_with_object({}) { |table, h|
13
+ h[table.node] = table.columns.each_with_object({}) { |column, i|
12
14
  i[column.name] = column.alias
13
15
  }
14
16
  }
15
- @name_and_alias_cache = tables.each_with_object({}) { |table,h|
16
- h[table.node] = table.columns.map { |column|
17
- [column.name, column.alias]
18
- }
17
+ @columns_cache = tables.each_with_object({}) { |table, h|
18
+ h[table.node] = table.columns
19
19
  }
20
20
  end
21
21
 
@@ -23,30 +23,23 @@ module ActiveRecord
23
23
  @tables.flat_map(&:column_aliases)
24
24
  end
25
25
 
26
- # An array of [column_name, alias] pairs for the table
27
26
  def column_aliases(node)
28
- @name_and_alias_cache[node]
27
+ @columns_cache[node]
29
28
  end
30
29
 
31
30
  def column_alias(node, column)
32
31
  @alias_cache[node][column]
33
32
  end
34
33
 
35
- class Table < Struct.new(:node, :columns) # :nodoc:
36
- def table
37
- Arel::Nodes::TableAlias.new node.table, node.aliased_table_name
38
- end
39
-
34
+ Table = Struct.new(:node, :columns) do # :nodoc:
40
35
  def column_aliases
41
- t = table
36
+ t = node.table
42
37
  columns.map { |column| t[column.name].as Arel.sql column.alias }
43
38
  end
44
39
  end
45
40
  Column = Struct.new(:name, :alias)
46
41
  end
47
42
 
48
- attr_reader :alias_tracker, :base_klass, :join_root
49
-
50
43
  def self.make_tree(associations)
51
44
  hash = {}
52
45
  walk_tree associations, hash
@@ -62,7 +55,7 @@ module ActiveRecord
62
55
  walk_tree assoc, hash
63
56
  end
64
57
  when Hash
65
- associations.each do |k,v|
58
+ associations.each do |k, v|
66
59
  cache = hash[k] ||= {}
67
60
  walk_tree v, cache
68
61
  end
@@ -71,69 +64,37 @@ module ActiveRecord
71
64
  end
72
65
  end
73
66
 
74
- # base is the base class on which operation is taking place.
75
- # associations is the list of associations which are joined using hash, symbol or array.
76
- # joins is the list of all string join commands and arel nodes.
77
- #
78
- # Example :
79
- #
80
- # class Physician < ActiveRecord::Base
81
- # has_many :appointments
82
- # has_many :patients, through: :appointments
83
- # end
84
- #
85
- # If I execute `@physician.patients.to_a` then
86
- # base # => Physician
87
- # associations # => []
88
- # joins # => [#<Arel::Nodes::InnerJoin: ...]
89
- #
90
- # However if I execute `Physician.joins(:appointments).to_a` then
91
- # base # => Physician
92
- # associations # => [:appointments]
93
- # joins # => []
94
- #
95
- def initialize(base, associations, joins)
96
- @alias_tracker = AliasTracker.create_with_joins(base.connection, base.table_name, joins, base.type_caster)
67
+ def initialize(base, table, associations, join_type)
97
68
  tree = self.class.make_tree associations
98
- @join_root = JoinBase.new base, build(tree, base)
99
- @join_root.children.each { |child| construct_tables! @join_root, child }
69
+ @join_root = JoinBase.new(base, table, build(tree, base))
70
+ @join_type = join_type
71
+ end
72
+
73
+ def base_klass
74
+ join_root.base_klass
100
75
  end
101
76
 
102
77
  def reflections
103
78
  join_root.drop(1).map!(&:reflection)
104
79
  end
105
80
 
106
- def join_constraints(outer_joins, join_type)
107
- joins = join_root.children.flat_map { |child|
81
+ def join_constraints(joins_to_add, alias_tracker)
82
+ @alias_tracker = alias_tracker
108
83
 
109
- if join_type == Arel::Nodes::OuterJoin
110
- make_left_outer_joins join_root, child
111
- else
112
- make_inner_joins join_root, child
113
- end
114
- }
84
+ construct_tables!(join_root)
85
+ joins = make_join_constraints(join_root, join_type)
115
86
 
116
- joins.concat outer_joins.flat_map { |oj|
87
+ joins.concat joins_to_add.flat_map { |oj|
88
+ construct_tables!(oj.join_root)
117
89
  if join_root.match? oj.join_root
118
- walk join_root, oj.join_root
90
+ walk(join_root, oj.join_root, oj.join_type)
119
91
  else
120
- oj.join_root.children.flat_map { |child|
121
- make_outer_joins oj.join_root, child
122
- }
92
+ make_join_constraints(oj.join_root, oj.join_type)
123
93
  end
124
94
  }
125
95
  end
126
96
 
127
- def aliases
128
- Aliases.new join_root.each_with_index.map { |join_part,i|
129
- columns = join_part.column_names.each_with_index.map { |column_name,j|
130
- Aliases::Column.new column_name, "t#{i}_r#{j}"
131
- }
132
- Aliases::Table.new(join_part, columns)
133
- }
134
- end
135
-
136
- def instantiate(result_set, aliases)
97
+ def instantiate(result_set, &block)
137
98
  primary_key = aliases.column_alias(join_root, join_root.primary_key)
138
99
 
139
100
  seen = Hash.new { |i, object_id|
@@ -142,9 +103,11 @@ module ActiveRecord
142
103
  }
143
104
  }
144
105
 
145
- model_cache = Hash.new { |h,klass| h[klass] = {} }
106
+ model_cache = Hash.new { |h, klass| h[klass] = {} }
146
107
  parents = model_cache[join_root]
108
+
147
109
  column_aliases = aliases.column_aliases join_root
110
+ column_aliases += explicit_selections(column_aliases, result_set)
148
111
 
149
112
  message_bus = ActiveSupport::Notifications.instrumenter
150
113
 
@@ -153,152 +116,156 @@ module ActiveRecord
153
116
  class_name: join_root.base_klass.name
154
117
  }
155
118
 
156
- message_bus.instrument('instantiation.active_record', payload) do
119
+ message_bus.instrument("instantiation.active_record", payload) do
157
120
  result_set.each { |row_hash|
158
121
  parent_key = primary_key ? row_hash[primary_key] : row_hash
159
- parent = parents[parent_key] ||= join_root.instantiate(row_hash, column_aliases)
160
- construct(parent, join_root, row_hash, result_set, seen, model_cache, aliases)
122
+ parent = parents[parent_key] ||= join_root.instantiate(row_hash, column_aliases, &block)
123
+ construct(parent, join_root, row_hash, seen, model_cache)
161
124
  }
162
125
  end
163
126
 
164
127
  parents.values
165
128
  end
166
129
 
167
- private
168
-
169
- def make_constraints(parent, child, tables, join_type)
170
- chain = child.reflection.chain
171
- foreign_table = parent.table
172
- foreign_klass = parent.base_klass
173
- child.join_constraints(foreign_table, foreign_klass, child, join_type, tables, child.reflection.scope_chain, chain)
130
+ def apply_column_aliases(relation)
131
+ relation._select!(-> { aliases.columns })
174
132
  end
175
133
 
176
- def make_outer_joins(parent, child)
177
- tables = table_aliases_for(parent, child)
178
- join_type = Arel::Nodes::OuterJoin
179
- info = make_constraints parent, child, tables, join_type
134
+ protected
135
+ attr_reader :join_root, :join_type
180
136
 
181
- [info] + child.children.flat_map { |c| make_outer_joins(child, c) }
182
- end
137
+ private
138
+ attr_reader :alias_tracker
183
139
 
184
- def make_left_outer_joins(parent, child)
185
- tables = child.tables
186
- join_type = Arel::Nodes::OuterJoin
187
- info = make_constraints parent, child, tables, join_type
140
+ def explicit_selections(root_column_aliases, result_set)
141
+ root_names = root_column_aliases.map(&:name).to_set
142
+ result_set.columns
143
+ .reject { |n| root_names.include?(n) || n =~ /\At\d+_r\d+\z/ }
144
+ .map { |n| Aliases::Column.new(n, n) }
145
+ end
188
146
 
189
- [info] + child.children.flat_map { |c| make_left_outer_joins(child, c) }
190
- end
147
+ def aliases
148
+ @aliases ||= Aliases.new join_root.each_with_index.map { |join_part, i|
149
+ columns = join_part.column_names.each_with_index.map { |column_name, j|
150
+ Aliases::Column.new column_name, "t#{i}_r#{j}"
151
+ }
152
+ Aliases::Table.new(join_part, columns)
153
+ }
154
+ end
191
155
 
192
- def make_inner_joins(parent, child)
193
- tables = child.tables
194
- join_type = Arel::Nodes::InnerJoin
195
- info = make_constraints parent, child, tables, join_type
156
+ def construct_tables!(join_root)
157
+ join_root.each_children do |parent, child|
158
+ child.tables = table_aliases_for(parent, child)
159
+ end
160
+ end
196
161
 
197
- [info] + child.children.flat_map { |c| make_inner_joins(child, c) }
198
- end
162
+ def make_join_constraints(join_root, join_type)
163
+ join_root.children.flat_map do |child|
164
+ make_constraints(join_root, child, join_type)
165
+ end
166
+ end
199
167
 
200
- def table_aliases_for(parent, node)
201
- node.reflection.chain.map { |reflection|
202
- alias_tracker.aliased_table_for(
203
- reflection.table_name,
204
- table_alias_for(reflection, parent, reflection != node.reflection)
205
- )
206
- }
207
- end
168
+ def make_constraints(parent, child, join_type)
169
+ foreign_table = parent.table
170
+ foreign_klass = parent.base_klass
171
+ joins = child.join_constraints(foreign_table, foreign_klass, join_type, alias_tracker)
172
+ joins.concat child.children.flat_map { |c| make_constraints(child, c, join_type) }
173
+ end
208
174
 
209
- def construct_tables!(parent, node)
210
- node.tables = table_aliases_for(parent, node)
211
- node.children.each { |child| construct_tables! node, child }
212
- end
175
+ def table_aliases_for(parent, node)
176
+ node.reflection.chain.map { |reflection|
177
+ alias_tracker.aliased_table_for(
178
+ reflection.table_name,
179
+ table_alias_for(reflection, parent, reflection != node.reflection),
180
+ reflection.klass.type_caster
181
+ )
182
+ }
183
+ end
213
184
 
214
- def table_alias_for(reflection, parent, join)
215
- name = "#{reflection.plural_name}_#{parent.table_name}"
216
- name << "_join" if join
217
- name
218
- end
185
+ def table_alias_for(reflection, parent, join)
186
+ name = reflection.alias_candidate(parent.table_name)
187
+ join ? "#{name}_join" : name
188
+ end
219
189
 
220
- def walk(left, right)
221
- intersection, missing = right.children.map { |node1|
222
- [left.children.find { |node2| node1.match? node2 }, node1]
223
- }.partition(&:first)
190
+ def walk(left, right, join_type)
191
+ intersection, missing = right.children.map { |node1|
192
+ [left.children.find { |node2| node1.match? node2 }, node1]
193
+ }.partition(&:first)
224
194
 
225
- ojs = missing.flat_map { |_,n| make_outer_joins left, n }
226
- intersection.flat_map { |l,r| walk l, r }.concat ojs
227
- end
195
+ joins = intersection.flat_map { |l, r| r.table = l.table; walk(l, r, join_type) }
196
+ joins.concat missing.flat_map { |_, n| make_constraints(left, n, join_type) }
197
+ end
228
198
 
229
- def find_reflection(klass, name)
230
- klass._reflect_on_association(name) or
231
- raise ConfigurationError, "Can't join '#{ klass.name }' to association named '#{ name }'; perhaps you misspelled it?"
232
- end
199
+ def find_reflection(klass, name)
200
+ klass._reflect_on_association(name) ||
201
+ raise(ConfigurationError, "Can't join '#{klass.name}' to association named '#{name}'; perhaps you misspelled it?")
202
+ end
233
203
 
234
- def build(associations, base_klass)
235
- associations.map do |name, right|
236
- reflection = find_reflection base_klass, name
237
- reflection.check_validity!
238
- reflection.check_eager_loadable!
204
+ def build(associations, base_klass)
205
+ associations.map do |name, right|
206
+ reflection = find_reflection base_klass, name
207
+ reflection.check_validity!
208
+ reflection.check_eager_loadable!
239
209
 
240
- if reflection.polymorphic?
241
- raise EagerLoadPolymorphicError.new(reflection)
242
- end
210
+ if reflection.polymorphic?
211
+ raise EagerLoadPolymorphicError.new(reflection)
212
+ end
243
213
 
244
- JoinAssociation.new reflection, build(right, reflection.klass)
214
+ JoinAssociation.new(reflection, build(right, reflection.klass))
215
+ end
245
216
  end
246
- end
247
-
248
- def construct(ar_parent, parent, row, rs, seen, model_cache, aliases)
249
- return if ar_parent.nil?
250
217
 
251
- parent.children.each do |node|
252
- if node.reflection.collection?
253
- other = ar_parent.association(node.reflection.name)
254
- other.loaded!
255
- elsif ar_parent.association_cached?(node.reflection.name)
256
- model = ar_parent.association(node.reflection.name).target
257
- construct(model, node, row, rs, seen, model_cache, aliases)
258
- next
259
- end
218
+ def construct(ar_parent, parent, row, seen, model_cache)
219
+ return if ar_parent.nil?
220
+
221
+ parent.children.each do |node|
222
+ if node.reflection.collection?
223
+ other = ar_parent.association(node.reflection.name)
224
+ other.loaded!
225
+ elsif ar_parent.association_cached?(node.reflection.name)
226
+ model = ar_parent.association(node.reflection.name).target
227
+ construct(model, node, row, seen, model_cache)
228
+ next
229
+ end
260
230
 
261
- key = aliases.column_alias(node, node.primary_key)
262
- id = row[key]
263
- if id.nil?
264
- nil_association = ar_parent.association(node.reflection.name)
265
- nil_association.loaded!
266
- next
267
- end
231
+ key = aliases.column_alias(node, node.primary_key)
232
+ id = row[key]
233
+ if id.nil?
234
+ nil_association = ar_parent.association(node.reflection.name)
235
+ nil_association.loaded!
236
+ next
237
+ end
268
238
 
269
- model = seen[ar_parent.object_id][node.base_klass][id]
239
+ model = seen[ar_parent.object_id][node][id]
270
240
 
271
- if model
272
- construct(model, node, row, rs, seen, model_cache, aliases)
273
- else
274
- model = construct_model(ar_parent, node, row, model_cache, id, aliases)
241
+ if model
242
+ construct(model, node, row, seen, model_cache)
243
+ else
244
+ model = construct_model(ar_parent, node, row, model_cache, id)
275
245
 
276
- if node.reflection.scope_for(node.base_klass).readonly_value
277
- model.readonly!
246
+ seen[ar_parent.object_id][node][id] = model
247
+ construct(model, node, row, seen, model_cache)
278
248
  end
279
-
280
- seen[ar_parent.object_id][node.base_klass][id] = model
281
- construct(model, node, row, rs, seen, model_cache, aliases)
282
249
  end
283
250
  end
284
- end
285
251
 
286
- def construct_model(record, node, row, model_cache, id, aliases)
287
- other = record.association(node.reflection.name)
252
+ def construct_model(record, node, row, model_cache, id)
253
+ other = record.association(node.reflection.name)
288
254
 
289
- model = model_cache[node][id] ||=
290
- node.instantiate(row, aliases.column_aliases(node)) do |m|
291
- other.set_inverse_instance(m)
255
+ model = model_cache[node][id] ||=
256
+ node.instantiate(row, aliases.column_aliases(node)) do |m|
257
+ other.set_inverse_instance(m)
258
+ end
259
+
260
+ if node.reflection.collection?
261
+ other.target.push(model)
262
+ else
263
+ other.target = model
292
264
  end
293
265
 
294
- if node.reflection.collection?
295
- other.target.push(model)
296
- else
297
- other.target = model
266
+ model.readonly! if node.readonly?
267
+ model
298
268
  end
299
-
300
- model
301
- end
302
269
  end
303
270
  end
304
271
  end