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,51 +1,44 @@
1
- require 'active_support/core_ext/string/conversions'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/string/conversions"
2
4
 
3
5
  module ActiveRecord
4
6
  module Associations
5
7
  # Keeps track of table aliases for ActiveRecord::Associations::JoinDependency
6
8
  class AliasTracker # :nodoc:
7
- attr_reader :aliases
8
-
9
- def self.create(connection, initial_table, type_caster)
10
- aliases = Hash.new(0)
11
- aliases[initial_table] = 1
12
- new connection, aliases, type_caster
13
- end
14
-
15
- def self.create_with_joins(connection, initial_table, joins, type_caster)
9
+ def self.create(connection, initial_table, joins, aliases = nil)
16
10
  if joins.empty?
17
- create(connection, initial_table, type_caster)
11
+ aliases ||= Hash.new(0)
12
+ elsif aliases
13
+ default_proc = aliases.default_proc || proc { 0 }
14
+ aliases.default_proc = proc { |h, k|
15
+ h[k] = initial_count_for(connection, k, joins) + default_proc.call(h, k)
16
+ }
18
17
  else
19
18
  aliases = Hash.new { |h, k|
20
19
  h[k] = initial_count_for(connection, k, joins)
21
20
  }
22
- aliases[initial_table] = 1
23
- new connection, aliases, type_caster
24
21
  end
22
+ aliases[initial_table] = 1
23
+ new(connection, aliases)
25
24
  end
26
25
 
27
26
  def self.initial_count_for(connection, name, table_joins)
28
- # quoted_name should be downcased as some database adapters (Oracle) return quoted name in uppercase
29
- quoted_name = connection.quote_table_name(name).downcase
27
+ quoted_name = nil
30
28
 
31
29
  counts = table_joins.map do |join|
32
30
  if join.is_a?(Arel::Nodes::StringJoin)
31
+ # quoted_name should be case ignored as some database adapters (Oracle) return quoted name in uppercase
32
+ quoted_name ||= connection.quote_table_name(name)
33
+
33
34
  # Table names + table aliases
34
- join.left.downcase.scan(
35
- /join(?:\s+\w+)?\s+(\S+\s+)?#{quoted_name}\son/
35
+ join.left.scan(
36
+ /JOIN(?:\s+\w+)?\s+(?:\S+\s+)?(?:#{quoted_name}|#{name})\sON/i
36
37
  ).size
37
- elsif join.respond_to? :left
38
- join.left.table_name == name ? 1 : 0
38
+ elsif join.is_a?(Arel::Nodes::Join)
39
+ join.left.name == name ? 1 : 0
39
40
  else
40
- # this branch is reached by two tests:
41
- #
42
- # activerecord/test/cases/associations/cascaded_eager_loading_test.rb:37
43
- # with :posts
44
- #
45
- # activerecord/test/cases/associations/eager_test.rb:1133
46
- # with :comments
47
- #
48
- 0
41
+ raise ArgumentError, "joins list should be initialized by list of Arel::Nodes::Join"
49
42
  end
50
43
  end
51
44
 
@@ -53,35 +46,36 @@ module ActiveRecord
53
46
  end
54
47
 
55
48
  # table_joins is an array of arel joins which might conflict with the aliases we assign here
56
- def initialize(connection, aliases, type_caster)
49
+ def initialize(connection, aliases)
57
50
  @aliases = aliases
58
51
  @connection = connection
59
- @type_caster = type_caster
60
52
  end
61
53
 
62
- def aliased_table_for(table_name, aliased_name)
63
- if aliases[table_name].zero?
54
+ def aliased_table_for(arel_table, table_name = nil)
55
+ table_name ||= arel_table.name
56
+
57
+ if aliases[table_name] == 0
64
58
  # If it's zero, we can have our table_name
65
59
  aliases[table_name] = 1
66
- Arel::Table.new(table_name, type_caster: @type_caster)
60
+ arel_table = arel_table.alias(table_name) if arel_table.name != table_name
67
61
  else
68
62
  # Otherwise, we need to use an alias
69
- aliased_name = @connection.table_alias_for(aliased_name)
63
+ aliased_name = @connection.table_alias_for(yield)
70
64
 
71
65
  # Update the count
72
- aliases[aliased_name] += 1
66
+ count = aliases[aliased_name] += 1
73
67
 
74
- table_alias = if aliases[aliased_name] > 1
75
- "#{truncate(aliased_name)}_#{aliases[aliased_name]}"
76
- else
77
- aliased_name
78
- end
79
- Arel::Table.new(table_name, type_caster: @type_caster).alias(table_alias)
68
+ aliased_name = "#{truncate(aliased_name)}_#{count}" if count > 1
69
+
70
+ arel_table = arel_table.alias(aliased_name)
80
71
  end
72
+
73
+ arel_table
81
74
  end
82
75
 
83
- private
76
+ attr_reader :aliases
84
77
 
78
+ private
85
79
  def truncate(name)
86
80
  name.slice(0, @connection.table_alias_length - 2)
87
81
  end
@@ -1,4 +1,4 @@
1
- require 'active_support/core_ext/array/wrap'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecord
4
4
  module Associations
@@ -15,11 +15,27 @@ module ActiveRecord
15
15
  # CollectionAssociation
16
16
  # HasManyAssociation + ForeignAssociation
17
17
  # HasManyThroughAssociation + ThroughAssociation
18
+ #
19
+ # Associations in Active Record are middlemen between the object that
20
+ # holds the association, known as the <tt>owner</tt>, and the associated
21
+ # result set, known as the <tt>target</tt>. Association metadata is available in
22
+ # <tt>reflection</tt>, which is an instance of <tt>ActiveRecord::Reflection::AssociationReflection</tt>.
23
+ #
24
+ # For example, given
25
+ #
26
+ # class Blog < ActiveRecord::Base
27
+ # has_many :posts
28
+ # end
29
+ #
30
+ # blog = Blog.first
31
+ #
32
+ # The association of <tt>blog.posts</tt> has the object +blog+ as its
33
+ # <tt>owner</tt>, the collection of its posts as <tt>target</tt>, and
34
+ # the <tt>reflection</tt> object represents a <tt>:has_many</tt> macro.
18
35
  class Association #:nodoc:
19
36
  attr_reader :owner, :target, :reflection
20
- attr_accessor :inversed
21
37
 
22
- delegate :options, :to => :reflection
38
+ delegate :options, to: :reflection
23
39
 
24
40
  def initialize(owner, reflection)
25
41
  reflection.check_validity!
@@ -30,14 +46,6 @@ module ActiveRecord
30
46
  reset_scope
31
47
  end
32
48
 
33
- # Returns the name of the table of the associated class:
34
- #
35
- # post.comments.aliased_table_name # => "comments"
36
- #
37
- def aliased_table_name
38
- klass.table_name
39
- end
40
-
41
49
  # Resets the \loaded flag to +false+ and sets the \target to +nil+.
42
50
  def reset
43
51
  @loaded = false
@@ -46,8 +54,14 @@ module ActiveRecord
46
54
  @inversed = false
47
55
  end
48
56
 
57
+ def reset_negative_cache # :nodoc:
58
+ reset if loaded? && target.nil?
59
+ end
60
+
49
61
  # Reloads the \target and returns +self+ on success.
50
- def reload
62
+ # The QueryCache is cleared if +force+ is true.
63
+ def reload(force = false)
64
+ klass.connection.clear_query_cache if force && klass
51
65
  reset
52
66
  reset_scope
53
67
  load_target
@@ -73,7 +87,7 @@ module ActiveRecord
73
87
  #
74
88
  # Note that if the target has not been loaded, it is not considered stale.
75
89
  def stale_target?
76
- !inversed && loaded? && @stale_state != stale_state
90
+ !@inversed && loaded? && @stale_state != stale_state
77
91
  end
78
92
 
79
93
  # Sets the target of this association to <tt>\target</tt>, and the \loaded flag to +true+.
@@ -83,18 +97,10 @@ module ActiveRecord
83
97
  end
84
98
 
85
99
  def scope
86
- target_scope.merge!(association_scope)
87
- end
88
-
89
- # The scope for this association.
90
- #
91
- # Note that the association_scope is merged into the target_scope only when the
92
- # scope method is called. This is because at that point the call may be surrounded
93
- # by scope.scoping { ... } or with_scope { ... } etc, which affects the scope which
94
- # actually gets built.
95
- def association_scope
96
- if klass
97
- @association_scope ||= AssociationScope.scope(self, klass.connection)
100
+ if (scope = klass.current_scope) && scope.try(:proxy_association) == self
101
+ scope.spawn
102
+ else
103
+ target_scope.merge!(association_scope)
98
104
  end
99
105
  end
100
106
 
@@ -104,31 +110,51 @@ module ActiveRecord
104
110
 
105
111
  # Set the inverse association, if possible
106
112
  def set_inverse_instance(record)
107
- if invertible_for?(record)
108
- inverse = record.association(inverse_reflection_for(record).name)
109
- inverse.target = owner
110
- inverse.inversed = true
113
+ if inverse = inverse_association_for(record)
114
+ inverse.inversed_from(owner)
115
+ end
116
+ record
117
+ end
118
+
119
+ def set_inverse_instance_from_queries(record)
120
+ if inverse = inverse_association_for(record)
121
+ inverse.inversed_from_queries(owner)
111
122
  end
112
123
  record
113
124
  end
114
125
 
126
+ # Remove the inverse association, if possible
127
+ def remove_inverse_instance(record)
128
+ if inverse = inverse_association_for(record)
129
+ inverse.inversed_from(nil)
130
+ end
131
+ end
132
+
133
+ def inversed_from(record)
134
+ self.target = record
135
+ @inversed = !!record
136
+ end
137
+
138
+ def inversed_from_queries(record)
139
+ if inversable?(record)
140
+ self.target = record
141
+ @inversed = true
142
+ else
143
+ @inversed = false
144
+ end
145
+ end
146
+
115
147
  # Returns the class of the target. belongs_to polymorphic overrides this to look at the
116
148
  # polymorphic_type field on the owner.
117
149
  def klass
118
150
  reflection.klass
119
151
  end
120
152
 
121
- # Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
122
- # through association's scope)
123
- def target_scope
124
- AssociationRelation.create(klass, klass.arel_table, klass.predicate_builder, self).merge!(klass.all)
125
- end
126
-
127
153
  def extensions
128
154
  extensions = klass.default_extensions | reflection.extensions
129
155
 
130
- if scope = reflection.scope
131
- extensions |= klass.unscoped.instance_exec(owner, &scope).extensions
156
+ if reflection.scope
157
+ extensions |= reflection.scope_for(klass.unscoped, owner).extensions
132
158
  end
133
159
 
134
160
  extensions
@@ -153,17 +179,9 @@ module ActiveRecord
153
179
  reset
154
180
  end
155
181
 
156
- def interpolate(sql, record = nil)
157
- if sql.respond_to?(:to_proc)
158
- owner.instance_exec(record, &sql)
159
- else
160
- sql
161
- end
162
- end
163
-
164
- # We can't dump @reflection since it contains the scope proc
182
+ # We can't dump @reflection and @through_reflection since it contains the scope proc
165
183
  def marshal_dump
166
- ivars = (instance_variables - [:@reflection]).map { |name| [name, instance_variable_get(name)] }
184
+ ivars = (instance_variables - [:@reflection, :@through_reflection]).map { |name| [name, instance_variable_get(name)] }
167
185
  [@reflection.name, ivars]
168
186
  end
169
187
 
@@ -176,36 +194,67 @@ module ActiveRecord
176
194
  def initialize_attributes(record, except_from_scope_attributes = nil) #:nodoc:
177
195
  except_from_scope_attributes ||= {}
178
196
  skip_assign = [reflection.foreign_key, reflection.type].compact
179
- assigned_keys = record.changed
197
+ assigned_keys = record.changed_attribute_names_to_save
180
198
  assigned_keys += except_from_scope_attributes.keys.map(&:to_s)
181
- attributes = create_scope.except(*(assigned_keys - skip_assign))
182
- record.assign_attributes(attributes)
199
+ attributes = scope_for_create.except!(*(assigned_keys - skip_assign))
200
+ record.send(:_assign_attributes, attributes) if attributes.any?
183
201
  set_inverse_instance(record)
184
202
  end
185
203
 
204
+ def create(attributes = nil, &block)
205
+ _create_record(attributes, &block)
206
+ end
207
+
208
+ def create!(attributes = nil, &block)
209
+ _create_record(attributes, true, &block)
210
+ end
211
+
186
212
  private
213
+ def find_target
214
+ if owner.strict_loading? && owner.validation_context.nil?
215
+ Base.strict_loading_violation!(owner: owner.class, association: klass)
216
+ end
187
217
 
188
- def find_target?
189
- !loaded? && (!owner.new_record? || foreign_key_present?) && klass
190
- end
218
+ if reflection.strict_loading? && owner.validation_context.nil?
219
+ Base.strict_loading_violation!(owner: owner.class, association: reflection.name)
220
+ end
221
+
222
+ scope = self.scope
223
+ return scope.to_a if skip_statement_cache?(scope)
191
224
 
192
- def creation_attributes
193
- attributes = {}
225
+ sc = reflection.association_scope_cache(klass, owner) do |params|
226
+ as = AssociationScope.create { params.bind }
227
+ target_scope.merge!(as.scope(self))
228
+ end
194
229
 
195
- if (reflection.has_one? || reflection.collection?) && !options[:through]
196
- attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key]
230
+ binds = AssociationScope.get_bind_values(owner, reflection.chain)
231
+ sc.execute(binds, klass.connection) { |record| set_inverse_instance(record) }
232
+ end
197
233
 
198
- if reflection.options[:as]
199
- attributes[reflection.type] = owner.class.base_class.name
200
- end
234
+ # The scope for this association.
235
+ #
236
+ # Note that the association_scope is merged into the target_scope only when the
237
+ # scope method is called. This is because at that point the call may be surrounded
238
+ # by scope.scoping { ... } or unscoped { ... } etc, which affects the scope which
239
+ # actually gets built.
240
+ def association_scope
241
+ if klass
242
+ @association_scope ||= AssociationScope.scope(self)
201
243
  end
244
+ end
245
+
246
+ # Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
247
+ # through association's scope)
248
+ def target_scope
249
+ AssociationRelation.create(klass, self).merge!(klass.scope_for_association)
250
+ end
202
251
 
203
- attributes
252
+ def scope_for_create
253
+ scope.scope_for_create
204
254
  end
205
255
 
206
- # Sets the owner attributes on the given record
207
- def set_owner_attributes(record)
208
- creation_attributes.each { |key, value| record[key] = value }
256
+ def find_target?
257
+ !loaded? && (!owner.new_record? || foreign_key_present?) && klass
209
258
  end
210
259
 
211
260
  # Returns true if there is a foreign key present on the owner which
@@ -227,12 +276,19 @@ module ActiveRecord
227
276
  unless record.is_a?(reflection.klass)
228
277
  fresh_class = reflection.class_name.safe_constantize
229
278
  unless fresh_class && record.is_a?(fresh_class)
230
- message = "#{reflection.class_name}(##{reflection.klass.object_id}) expected, got #{record.class}(##{record.class.object_id})"
279
+ message = "#{reflection.class_name}(##{reflection.klass.object_id}) expected, "\
280
+ "got #{record.inspect} which is an instance of #{record.class}(##{record.class.object_id})"
231
281
  raise ActiveRecord::AssociationTypeMismatch, message
232
282
  end
233
283
  end
234
284
  end
235
285
 
286
+ def inverse_association_for(record)
287
+ if invertible_for?(record)
288
+ record.association(inverse_reflection_for(record).name)
289
+ end
290
+ end
291
+
236
292
  # Can be redefined by subclasses, notably polymorphic belongs_to
237
293
  # The record parameter is necessary to support polymorphic inverses as we must check for
238
294
  # the association in the specific class of the record.
@@ -248,30 +304,49 @@ module ActiveRecord
248
304
 
249
305
  # Returns true if record contains the foreign_key
250
306
  def foreign_key_for?(record)
251
- record.has_attribute?(reflection.foreign_key)
307
+ record._has_attribute?(reflection.foreign_key)
252
308
  end
253
309
 
254
310
  # This should be implemented to return the values of the relevant key(s) on the owner,
255
311
  # so that when stale_state is different from the value stored on the last find_target,
256
312
  # the target is stale.
257
313
  #
258
- # This is only relevant to certain associations, which is why it returns nil by default.
314
+ # This is only relevant to certain associations, which is why it returns +nil+ by default.
259
315
  def stale_state
260
316
  end
261
317
 
262
318
  def build_record(attributes)
263
319
  reflection.build_association(attributes) do |record|
264
320
  initialize_attributes(record, attributes)
321
+ yield(record) if block_given?
265
322
  end
266
323
  end
267
324
 
268
325
  # Returns true if statement cache should be skipped on the association reader.
269
- def skip_statement_cache?
326
+ def skip_statement_cache?(scope)
270
327
  reflection.has_scope? ||
271
328
  scope.eager_loading? ||
272
329
  klass.scope_attributes? ||
273
330
  reflection.source_reflection.active_record.default_scopes.any?
274
331
  end
332
+
333
+ def enqueue_destroy_association(options)
334
+ owner.class.destroy_association_async_job&.perform_later(**options)
335
+ end
336
+
337
+ def inversable?(record)
338
+ record &&
339
+ ((!record.persisted? || !owner.persisted?) || matches_foreign_key?(record))
340
+ end
341
+
342
+ def matches_foreign_key?(record)
343
+ if foreign_key_for?(record)
344
+ record.read_attribute(reflection.foreign_key) == owner.id ||
345
+ (foreign_key_for?(owner) && owner.read_attribute(reflection.foreign_key) == record.id)
346
+ else
347
+ owner.read_attribute(reflection.foreign_key) == record.id
348
+ end
349
+ end
275
350
  end
276
351
  end
277
352
  end