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
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class DatabaseConfigurations
5
+ # ActiveRecord::Base.configurations will return either a HashConfig or
6
+ # UrlConfig respectively. It will never return a DatabaseConfig object,
7
+ # as this is the parent class for the types of database configuration objects.
8
+ class DatabaseConfig # :nodoc:
9
+ attr_reader :env_name, :name
10
+
11
+ attr_accessor :owner_name
12
+
13
+ def initialize(env_name, name)
14
+ @env_name = env_name
15
+ @name = name
16
+ end
17
+
18
+ def spec_name
19
+ @name
20
+ end
21
+ deprecate spec_name: "please use name instead"
22
+
23
+ def config
24
+ raise NotImplementedError
25
+ end
26
+
27
+ def adapter_method
28
+ "#{adapter}_connection"
29
+ end
30
+
31
+ def host
32
+ raise NotImplementedError
33
+ end
34
+
35
+ def database
36
+ raise NotImplementedError
37
+ end
38
+
39
+ def _database=(database)
40
+ raise NotImplementedError
41
+ end
42
+
43
+ def adapter
44
+ raise NotImplementedError
45
+ end
46
+
47
+ def pool
48
+ raise NotImplementedError
49
+ end
50
+
51
+ def checkout_timeout
52
+ raise NotImplementedError
53
+ end
54
+
55
+ def reaping_frequency
56
+ raise NotImplementedError
57
+ end
58
+
59
+ def idle_timeout
60
+ raise NotImplementedError
61
+ end
62
+
63
+ def replica?
64
+ raise NotImplementedError
65
+ end
66
+
67
+ def migrations_paths
68
+ raise NotImplementedError
69
+ end
70
+
71
+ def for_current_env?
72
+ env_name == ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
73
+ end
74
+
75
+ def schema_cache_path
76
+ raise NotImplementedError
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class DatabaseConfigurations
5
+ # A HashConfig object is created for each database configuration entry that
6
+ # is created from a hash.
7
+ #
8
+ # A hash config:
9
+ #
10
+ # { "development" => { "database" => "db_name" } }
11
+ #
12
+ # Becomes:
13
+ #
14
+ # #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10
15
+ # @env_name="development", @name="primary", @config={database: "db_name"}>
16
+ #
17
+ # ==== Options
18
+ #
19
+ # * <tt>:env_name</tt> - The Rails environment, i.e. "development".
20
+ # * <tt>:name</tt> - The db config name. In a standard two-tier
21
+ # database configuration this will default to "primary". In a multiple
22
+ # database three-tier database configuration this corresponds to the name
23
+ # used in the second tier, for example "primary_readonly".
24
+ # * <tt>:config</tt> - The config hash. This is the hash that contains the
25
+ # database adapter, name, and other important information for database
26
+ # connections.
27
+ class HashConfig < DatabaseConfig
28
+ attr_reader :configuration_hash
29
+ def initialize(env_name, name, configuration_hash)
30
+ super(env_name, name)
31
+ @configuration_hash = configuration_hash.symbolize_keys.freeze
32
+ end
33
+
34
+ def config
35
+ ActiveSupport::Deprecation.warn("DatabaseConfig#config will be removed in 6.2.0 in favor of DatabaseConfigurations#configuration_hash which returns a hash with symbol keys")
36
+ configuration_hash.stringify_keys
37
+ end
38
+
39
+ # Determines whether a database configuration is for a replica / readonly
40
+ # connection. If the +replica+ key is present in the config, +replica?+ will
41
+ # return +true+.
42
+ def replica?
43
+ configuration_hash[:replica]
44
+ end
45
+
46
+ # The migrations paths for a database configuration. If the
47
+ # +migrations_paths+ key is present in the config, +migrations_paths+
48
+ # will return its value.
49
+ def migrations_paths
50
+ configuration_hash[:migrations_paths]
51
+ end
52
+
53
+ def host
54
+ configuration_hash[:host]
55
+ end
56
+
57
+ def database
58
+ configuration_hash[:database]
59
+ end
60
+
61
+ def _database=(database) # :nodoc:
62
+ @configuration_hash = configuration_hash.merge(database: database).freeze
63
+ end
64
+
65
+ def pool
66
+ (configuration_hash[:pool] || 5).to_i
67
+ end
68
+
69
+ def checkout_timeout
70
+ (configuration_hash[:checkout_timeout] || 5).to_f
71
+ end
72
+
73
+ # +reaping_frequency+ is configurable mostly for historical reasons, but it could
74
+ # also be useful if someone wants a very low +idle_timeout+.
75
+ def reaping_frequency
76
+ configuration_hash.fetch(:reaping_frequency, 60)&.to_f
77
+ end
78
+
79
+ def idle_timeout
80
+ timeout = configuration_hash.fetch(:idle_timeout, 300).to_f
81
+ timeout if timeout > 0
82
+ end
83
+
84
+ def adapter
85
+ configuration_hash[:adapter]
86
+ end
87
+
88
+ # The path to the schema cache dump file for a database.
89
+ # If omitted, the filename will be read from ENV or a
90
+ # default will be derived.
91
+ def schema_cache_path
92
+ configuration_hash[:schema_cache_path]
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class DatabaseConfigurations
5
+ # A UrlConfig object is created for each database configuration
6
+ # entry that is created from a URL. This can either be a URL string
7
+ # or a hash with a URL in place of the config hash.
8
+ #
9
+ # A URL config:
10
+ #
11
+ # postgres://localhost/foo
12
+ #
13
+ # Becomes:
14
+ #
15
+ # #<ActiveRecord::DatabaseConfigurations::UrlConfig:0x00007fdc3238f340
16
+ # @env_name="default_env", @name="primary",
17
+ # @config={adapter: "postgresql", database: "foo", host: "localhost"},
18
+ # @url="postgres://localhost/foo">
19
+ #
20
+ # ==== Options
21
+ #
22
+ # * <tt>:env_name</tt> - The Rails environment, ie "development".
23
+ # * <tt>:name</tt> - The db config name. In a standard two-tier
24
+ # database configuration this will default to "primary". In a multiple
25
+ # database three-tier database configuration this corresponds to the name
26
+ # used in the second tier, for example "primary_readonly".
27
+ # * <tt>:url</tt> - The database URL.
28
+ # * <tt>:config</tt> - The config hash. This is the hash that contains the
29
+ # database adapter, name, and other important information for database
30
+ # connections.
31
+ class UrlConfig < HashConfig
32
+ attr_reader :url
33
+
34
+ def initialize(env_name, name, url, configuration_hash = {})
35
+ super(env_name, name, configuration_hash)
36
+
37
+ @url = url
38
+ @configuration_hash = @configuration_hash.merge(build_url_hash).freeze
39
+ end
40
+
41
+ private
42
+ # Return a Hash that can be merged into the main config that represents
43
+ # the passed in url
44
+ def build_url_hash
45
+ if url.nil? || url.start_with?("jdbc:")
46
+ { url: url }
47
+ else
48
+ ConnectionUrlResolver.new(url).to_hash
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,209 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/string/inquiry"
4
+
5
+ module ActiveRecord
6
+ # == Delegated types
7
+ #
8
+ # Class hierarchies can map to relational database tables in many ways. Active Record, for example, offers
9
+ # purely abstract classes, where the superclass doesn't persist any attributes, and single-table inheritance,
10
+ # where all attributes from all levels of the hierarchy are represented in a single table. Both have their
11
+ # places, but neither are without their drawbacks.
12
+ #
13
+ # The problem with purely abstract classes is that all concrete subclasses must persist all the shared
14
+ # attributes themselves in their own tables (also known as class-table inheritance). This makes it hard to
15
+ # do queries across the hierarchy. For example, imagine you have the following hierarchy:
16
+ #
17
+ # Entry < ApplicationRecord
18
+ # Message < Entry
19
+ # Comment < Entry
20
+ #
21
+ # How do you show a feed that has both +Message+ and +Comment+ records, which can be easily paginated?
22
+ # Well, you can't! Messages are backed by a messages table and comments by a comments table. You can't
23
+ # pull from both tables at once and use a consistent OFFSET/LIMIT scheme.
24
+ #
25
+ # You can get around the pagination problem by using single-table inheritance, but now you're forced into
26
+ # a single mega table with all the attributes from all subclasses. No matter how divergent. If a Message
27
+ # has a subject, but the comment does not, well, now the comment does anyway! So STI works best when there's
28
+ # little divergence between the subclasses and their attributes.
29
+ #
30
+ # But there's a third way: Delegated types. With this approach, the "superclass" is a concrete class
31
+ # that is represented by its own table, where all the superclass attributes that are shared amongst all the
32
+ # "subclasses" are stored. And then each of the subclasses have their own individual tables for additional
33
+ # attributes that are particular to their implementation. This is similar to what's called multi-table
34
+ # inheritance in Django, but instead of actual inheritance, this approach uses delegation to form the
35
+ # hierarchy and share responsibilities.
36
+ #
37
+ # Let's look at that entry/message/comment example using delegated types:
38
+ #
39
+ # # Schema: entries[ id, account_id, creator_id, created_at, updated_at, entryable_type, entryable_id ]
40
+ # class Entry < ApplicationRecord
41
+ # belongs_to :account
42
+ # belongs_to :creator
43
+ # delegated_type :entryable, types: %w[ Message Comment ]
44
+ # end
45
+ #
46
+ # module Entryable
47
+ # extend ActiveSupport::Concern
48
+ #
49
+ # included do
50
+ # has_one :entry, as: :entryable, touch: true
51
+ # end
52
+ # end
53
+ #
54
+ # # Schema: messages[ id, subject ]
55
+ # class Message < ApplicationRecord
56
+ # include Entryable
57
+ # has_rich_text :content
58
+ # end
59
+ #
60
+ # # Schema: comments[ id, content ]
61
+ # class Comment < ApplicationRecord
62
+ # include Entryable
63
+ # end
64
+ #
65
+ # As you can see, neither +Message+ nor +Comment+ are meant to stand alone. Crucial metadata for both classes
66
+ # resides in the +Entry+ "superclass". But the +Entry+ absolutely can stand alone in terms of querying capacity
67
+ # in particular. You can now easily do things like:
68
+ #
69
+ # Account.entries.order(created_at: :desc).limit(50)
70
+ #
71
+ # Which is exactly what you want when displaying both comments and messages together. The entry itself can
72
+ # be rendered as its delegated type easily, like so:
73
+ #
74
+ # # entries/_entry.html.erb
75
+ # <%= render "entries/entryables/#{entry.entryable_name}", entry: entry %>
76
+ #
77
+ # # entries/entryables/_message.html.erb
78
+ # <div class="message">
79
+ # Posted on <%= entry.created_at %> by <%= entry.creator.name %>: <%= entry.message.content %>
80
+ # </div>
81
+ #
82
+ # # entries/entryables/_comment.html.erb
83
+ # <div class="comment">
84
+ # <%= entry.creator.name %> said: <%= entry.comment.content %>
85
+ # </div>
86
+ #
87
+ # == Sharing behavior with concerns and controllers
88
+ #
89
+ # The entry "superclass" also serves as a perfect place to put all that shared logic that applies to both
90
+ # messages and comments, and which acts primarily on the shared attributes. Imagine:
91
+ #
92
+ # class Entry < ApplicationRecord
93
+ # include Eventable, Forwardable, Redeliverable
94
+ # end
95
+ #
96
+ # Which allows you to have controllers for things like +ForwardsController+ and +RedeliverableController+
97
+ # that both act on entries, and thus provide the shared functionality to both messages and comments.
98
+ #
99
+ # == Creating new records
100
+ #
101
+ # You create a new record that uses delegated typing by creating the delegator and delegatee at the same time,
102
+ # like so:
103
+ #
104
+ # Entry.create! entryable: Comment.new(content: "Hello!"), creator: Current.user
105
+ #
106
+ # If you need more complicated composition, or you need to perform dependent validation, you should build a factory
107
+ # method or class to take care of the complicated needs. This could be as simple as:
108
+ #
109
+ # class Entry < ApplicationRecord
110
+ # def self.create_with_comment(content, creator: Current.user)
111
+ # create! entryable: Comment.new(content: content), creator: creator
112
+ # end
113
+ # end
114
+ #
115
+ # == Adding further delegation
116
+ #
117
+ # The delegated type shouldn't just answer the question of what the underlying class is called. In fact, that's
118
+ # an anti-pattern most of the time. The reason you're building this hierarchy is to take advantage of polymorphism.
119
+ # So here's a simple example of that:
120
+ #
121
+ # class Entry < ApplicationRecord
122
+ # delegated_type :entryable, types: %w[ Message Comment ]
123
+ # delegate :title, to: :entryable
124
+ # end
125
+ #
126
+ # class Message < ApplicationRecord
127
+ # def title
128
+ # subject
129
+ # end
130
+ # end
131
+ #
132
+ # class Comment < ApplicationRecord
133
+ # def title
134
+ # content.truncate(20)
135
+ # end
136
+ # end
137
+ #
138
+ # Now you can list a bunch of entries, call +Entry#title+, and polymorphism will provide you with the answer.
139
+ module DelegatedType
140
+ # Defines this as a class that'll delegate its type for the passed +role+ to the class references in +types+.
141
+ # That'll create a polymorphic +belongs_to+ relationship to that +role+, and it'll add all the delegated
142
+ # type convenience methods:
143
+ #
144
+ # class Entry < ApplicationRecord
145
+ # delegated_type :entryable, types: %w[ Message Comment ], dependent: :destroy
146
+ # end
147
+ #
148
+ # Entry#entryable_class # => +Message+ or +Comment+
149
+ # Entry#entryable_name # => "message" or "comment"
150
+ # Entry.messages # => Entry.where(entryable_type: "Message")
151
+ # Entry#message? # => true when entryable_type == "Message"
152
+ # Entry#message # => returns the message record, when entryable_type == "Message", otherwise nil
153
+ # Entry#message_id # => returns entryable_id, when entryable_type == "Message", otherwise nil
154
+ # Entry.comments # => Entry.where(entryable_type: "Comment")
155
+ # Entry#comment? # => true when entryable_type == "Comment"
156
+ # Entry#comment # => returns the comment record, when entryable_type == "Comment", otherwise nil
157
+ # Entry#comment_id # => returns entryable_id, when entryable_type == "Comment", otherwise nil
158
+ #
159
+ # The +options+ are passed directly to the +belongs_to+ call, so this is where you declare +dependent+ etc.
160
+ #
161
+ # You can also declare namespaced types:
162
+ #
163
+ # class Entry < ApplicationRecord
164
+ # delegated_type :entryable, types: %w[ Message Comment Access::NoticeMessage ], dependent: :destroy
165
+ # end
166
+ #
167
+ # Entry.access_notice_messages
168
+ # entry.access_notice_message
169
+ # entry.access_notice_message?
170
+ def delegated_type(role, types:, **options)
171
+ belongs_to role, options.delete(:scope), **options.merge(polymorphic: true)
172
+ define_delegated_type_methods role, types: types
173
+ end
174
+
175
+ private
176
+ def define_delegated_type_methods(role, types:)
177
+ role_type = "#{role}_type"
178
+ role_id = "#{role}_id"
179
+
180
+ define_method "#{role}_class" do
181
+ public_send("#{role}_type").constantize
182
+ end
183
+
184
+ define_method "#{role}_name" do
185
+ public_send("#{role}_class").model_name.singular.inquiry
186
+ end
187
+
188
+ types.each do |type|
189
+ scope_name = type.tableize.gsub("/", "_")
190
+ singular = scope_name.singularize
191
+ query = "#{singular}?"
192
+
193
+ scope scope_name, -> { where(role_type => type) }
194
+
195
+ define_method query do
196
+ public_send(role_type) == type
197
+ end
198
+
199
+ define_method singular do
200
+ public_send(role) if public_send(query)
201
+ end
202
+
203
+ define_method "#{singular}_id" do
204
+ public_send(role_id) if public_send(query)
205
+ end
206
+ end
207
+ end
208
+ end
209
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class DestroyAssociationAsyncError < StandardError
5
+ end
6
+
7
+ # Job to destroy the records associated with a destroyed record in background.
8
+ class DestroyAssociationAsyncJob < ActiveJob::Base
9
+ queue_as { ActiveRecord::Base.queues[:destroy] }
10
+
11
+ discard_on ActiveJob::DeserializationError
12
+
13
+ def perform(
14
+ owner_model_name: nil, owner_id: nil,
15
+ association_class: nil, association_ids: nil, association_primary_key_column: nil,
16
+ ensuring_owner_was_method: nil
17
+ )
18
+ association_model = association_class.constantize
19
+ owner_class = owner_model_name.constantize
20
+ owner = owner_class.find_by(owner_class.primary_key.to_sym => owner_id)
21
+
22
+ if !owner_destroyed?(owner, ensuring_owner_was_method)
23
+ raise DestroyAssociationAsyncError, "owner record not destroyed"
24
+ end
25
+
26
+ association_model.where(association_primary_key_column => association_ids).find_each do |r|
27
+ r.destroy
28
+ end
29
+ end
30
+
31
+ private
32
+ def owner_destroyed?(owner, ensuring_owner_was_method)
33
+ !owner || (ensuring_owner_was_method && owner.public_send(ensuring_owner_was_method))
34
+ end
35
+ end
36
+ end