activerecord 6.0.0 → 7.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (376) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +996 -594
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +34 -34
  5. data/examples/performance.rb +2 -2
  6. data/lib/active_record/aggregations.rb +22 -20
  7. data/lib/active_record/association_relation.rb +22 -12
  8. data/lib/active_record/associations/alias_tracker.rb +41 -30
  9. data/lib/active_record/associations/association.rb +106 -41
  10. data/lib/active_record/associations/association_scope.rb +30 -21
  11. data/lib/active_record/associations/belongs_to_association.rb +69 -14
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +20 -6
  13. data/lib/active_record/associations/builder/association.rb +39 -6
  14. data/lib/active_record/associations/builder/belongs_to.rb +47 -17
  15. data/lib/active_record/associations/builder/collection_association.rb +14 -6
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -10
  17. data/lib/active_record/associations/builder/has_many.rb +7 -3
  18. data/lib/active_record/associations/builder/has_one.rb +13 -16
  19. data/lib/active_record/associations/builder/singular_association.rb +7 -3
  20. data/lib/active_record/associations/collection_association.rb +90 -53
  21. data/lib/active_record/associations/collection_proxy.rb +54 -19
  22. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  23. data/lib/active_record/associations/errors.rb +265 -0
  24. data/lib/active_record/associations/foreign_association.rb +21 -1
  25. data/lib/active_record/associations/has_many_association.rb +41 -10
  26. data/lib/active_record/associations/has_many_through_association.rb +29 -12
  27. data/lib/active_record/associations/has_one_association.rb +33 -9
  28. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  29. data/lib/active_record/associations/join_dependency/join_association.rb +41 -17
  30. data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
  31. data/lib/active_record/associations/join_dependency.rb +97 -54
  32. data/lib/active_record/associations/nested_error.rb +47 -0
  33. data/lib/active_record/associations/preloader/association.rb +237 -54
  34. data/lib/active_record/associations/preloader/batch.rb +48 -0
  35. data/lib/active_record/associations/preloader/branch.rb +153 -0
  36. data/lib/active_record/associations/preloader/through_association.rb +51 -17
  37. data/lib/active_record/associations/preloader.rb +55 -121
  38. data/lib/active_record/associations/singular_association.rb +16 -4
  39. data/lib/active_record/associations/through_association.rb +26 -15
  40. data/lib/active_record/associations.rb +454 -440
  41. data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
  42. data/lib/active_record/attribute_assignment.rb +11 -14
  43. data/lib/active_record/attribute_methods/before_type_cast.rb +36 -11
  44. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  45. data/lib/active_record/attribute_methods/dirty.rb +75 -34
  46. data/lib/active_record/attribute_methods/primary_key.rb +53 -31
  47. data/lib/active_record/attribute_methods/query.rb +31 -22
  48. data/lib/active_record/attribute_methods/read.rb +16 -17
  49. data/lib/active_record/attribute_methods/serialization.rb +177 -35
  50. data/lib/active_record/attribute_methods/time_zone_conversion.rb +18 -15
  51. data/lib/active_record/attribute_methods/write.rb +16 -28
  52. data/lib/active_record/attribute_methods.rb +227 -100
  53. data/lib/active_record/attributes.rb +94 -56
  54. data/lib/active_record/autosave_association.rb +119 -73
  55. data/lib/active_record/base.rb +31 -21
  56. data/lib/active_record/callbacks.rb +168 -55
  57. data/lib/active_record/coders/column_serializer.rb +61 -0
  58. data/lib/active_record/coders/json.rb +1 -1
  59. data/lib/active_record/coders/yaml_column.rb +70 -25
  60. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +284 -0
  61. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
  62. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +79 -0
  63. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +367 -565
  64. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -57
  65. data/lib/active_record/connection_adapters/abstract/database_statements.rb +277 -89
  66. data/lib/active_record/connection_adapters/abstract/query_cache.rb +241 -69
  67. data/lib/active_record/connection_adapters/abstract/quoting.rb +122 -134
  68. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  69. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -116
  70. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +324 -72
  71. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +17 -4
  72. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +611 -211
  73. data/lib/active_record/connection_adapters/abstract/transaction.rb +425 -82
  74. data/lib/active_record/connection_adapters/abstract_adapter.rb +698 -211
  75. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +464 -239
  76. data/lib/active_record/connection_adapters/column.rb +28 -1
  77. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  78. data/lib/active_record/connection_adapters/mysql/column.rb +2 -1
  79. data/lib/active_record/connection_adapters/mysql/database_statements.rb +32 -137
  80. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  81. data/lib/active_record/connection_adapters/mysql/quoting.rb +90 -43
  82. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +41 -7
  83. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +18 -1
  84. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +13 -4
  85. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +53 -15
  86. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  87. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
  88. data/lib/active_record/connection_adapters/mysql2_adapter.rb +127 -63
  89. data/lib/active_record/connection_adapters/pool_config.rb +83 -0
  90. data/lib/active_record/connection_adapters/pool_manager.rb +57 -0
  91. data/lib/active_record/connection_adapters/postgresql/column.rb +54 -2
  92. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +127 -100
  93. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  94. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +9 -5
  95. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +10 -2
  96. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +15 -2
  97. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  98. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -15
  99. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
  101. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +5 -4
  103. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  104. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
  105. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +35 -8
  106. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  109. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
  110. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +23 -4
  111. data/lib/active_record/connection_adapters/postgresql/oid.rb +4 -0
  112. data/lib/active_record/connection_adapters/postgresql/quoting.rb +139 -106
  113. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -2
  114. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +98 -4
  115. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +176 -4
  116. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -1
  117. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +462 -118
  118. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  119. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -11
  120. data/lib/active_record/connection_adapters/postgresql_adapter.rb +585 -295
  121. data/lib/active_record/connection_adapters/schema_cache.rb +399 -60
  122. data/lib/active_record/connection_adapters/sql_type_metadata.rb +8 -0
  123. data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
  124. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +99 -48
  125. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +80 -54
  126. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +27 -1
  127. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +20 -0
  128. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
  129. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +102 -24
  130. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +425 -174
  131. data/lib/active_record/connection_adapters/statement_pool.rb +7 -1
  132. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
  133. data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
  134. data/lib/active_record/connection_adapters.rb +176 -0
  135. data/lib/active_record/connection_handling.rb +243 -115
  136. data/lib/active_record/core.rb +481 -199
  137. data/lib/active_record/counter_cache.rb +69 -32
  138. data/lib/active_record/database_configurations/connection_url_resolver.rb +107 -0
  139. data/lib/active_record/database_configurations/database_config.rb +77 -10
  140. data/lib/active_record/database_configurations/hash_config.rb +148 -26
  141. data/lib/active_record/database_configurations/url_config.rb +44 -45
  142. data/lib/active_record/database_configurations.rb +190 -114
  143. data/lib/active_record/delegated_type.rb +279 -0
  144. data/lib/active_record/deprecator.rb +7 -0
  145. data/lib/active_record/destroy_association_async_job.rb +38 -0
  146. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  147. data/lib/active_record/dynamic_matchers.rb +5 -6
  148. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  149. data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
  150. data/lib/active_record/encryption/cipher.rb +53 -0
  151. data/lib/active_record/encryption/config.rb +68 -0
  152. data/lib/active_record/encryption/configurable.rb +60 -0
  153. data/lib/active_record/encryption/context.rb +42 -0
  154. data/lib/active_record/encryption/contexts.rb +76 -0
  155. data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
  156. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  157. data/lib/active_record/encryption/encryptable_record.rb +230 -0
  158. data/lib/active_record/encryption/encrypted_attribute_type.rb +175 -0
  159. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  160. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  161. data/lib/active_record/encryption/encryptor.rb +171 -0
  162. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  163. data/lib/active_record/encryption/errors.rb +15 -0
  164. data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
  165. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  166. data/lib/active_record/encryption/key.rb +28 -0
  167. data/lib/active_record/encryption/key_generator.rb +53 -0
  168. data/lib/active_record/encryption/key_provider.rb +46 -0
  169. data/lib/active_record/encryption/message.rb +33 -0
  170. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  171. data/lib/active_record/encryption/message_serializer.rb +96 -0
  172. data/lib/active_record/encryption/null_encryptor.rb +25 -0
  173. data/lib/active_record/encryption/properties.rb +76 -0
  174. data/lib/active_record/encryption/read_only_null_encryptor.rb +28 -0
  175. data/lib/active_record/encryption/scheme.rb +100 -0
  176. data/lib/active_record/encryption.rb +58 -0
  177. data/lib/active_record/enum.rb +224 -73
  178. data/lib/active_record/errors.rb +254 -36
  179. data/lib/active_record/explain.rb +30 -17
  180. data/lib/active_record/explain_registry.rb +11 -6
  181. data/lib/active_record/explain_subscriber.rb +2 -2
  182. data/lib/active_record/fixture_set/file.rb +22 -15
  183. data/lib/active_record/fixture_set/model_metadata.rb +15 -6
  184. data/lib/active_record/fixture_set/render_context.rb +3 -1
  185. data/lib/active_record/fixture_set/table_row.rb +88 -16
  186. data/lib/active_record/fixture_set/table_rows.rb +4 -5
  187. data/lib/active_record/fixtures.rb +229 -116
  188. data/lib/active_record/future_result.rb +178 -0
  189. data/lib/active_record/gem_version.rb +4 -4
  190. data/lib/active_record/inheritance.rb +121 -48
  191. data/lib/active_record/insert_all.rb +178 -29
  192. data/lib/active_record/integration.rb +16 -14
  193. data/lib/active_record/internal_metadata.rb +132 -21
  194. data/lib/active_record/legacy_yaml_adapter.rb +3 -36
  195. data/lib/active_record/locking/optimistic.rb +64 -33
  196. data/lib/active_record/locking/pessimistic.rb +21 -8
  197. data/lib/active_record/log_subscriber.rb +61 -30
  198. data/lib/active_record/marshalling.rb +59 -0
  199. data/lib/active_record/message_pack.rb +124 -0
  200. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  201. data/lib/active_record/middleware/database_selector/resolver.rb +19 -19
  202. data/lib/active_record/middleware/database_selector.rb +25 -13
  203. data/lib/active_record/middleware/shard_selector.rb +62 -0
  204. data/lib/active_record/migration/command_recorder.rb +160 -55
  205. data/lib/active_record/migration/compatibility.rb +286 -43
  206. data/lib/active_record/migration/default_strategy.rb +22 -0
  207. data/lib/active_record/migration/execution_strategy.rb +19 -0
  208. data/lib/active_record/migration/join_table.rb +1 -2
  209. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  210. data/lib/active_record/migration.rb +421 -193
  211. data/lib/active_record/model_schema.rb +217 -125
  212. data/lib/active_record/nested_attributes.rb +62 -27
  213. data/lib/active_record/no_touching.rb +4 -4
  214. data/lib/active_record/normalization.rb +163 -0
  215. data/lib/active_record/persistence.rb +322 -319
  216. data/lib/active_record/promise.rb +84 -0
  217. data/lib/active_record/query_cache.rb +18 -15
  218. data/lib/active_record/query_logs.rb +193 -0
  219. data/lib/active_record/query_logs_formatter.rb +41 -0
  220. data/lib/active_record/querying.rb +54 -14
  221. data/lib/active_record/railtie.rb +250 -72
  222. data/lib/active_record/railties/console_sandbox.rb +2 -4
  223. data/lib/active_record/railties/controller_runtime.rb +25 -11
  224. data/lib/active_record/railties/databases.rake +312 -197
  225. data/lib/active_record/railties/job_runtime.rb +23 -0
  226. data/lib/active_record/readonly_attributes.rb +45 -3
  227. data/lib/active_record/reflection.rb +389 -146
  228. data/lib/active_record/relation/batches/batch_enumerator.rb +61 -16
  229. data/lib/active_record/relation/batches.rb +214 -73
  230. data/lib/active_record/relation/calculations.rb +379 -124
  231. data/lib/active_record/relation/delegation.rb +36 -23
  232. data/lib/active_record/relation/finder_methods.rb +159 -49
  233. data/lib/active_record/relation/from_clause.rb +5 -1
  234. data/lib/active_record/relation/merger.rb +41 -33
  235. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -11
  236. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -7
  237. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +20 -13
  238. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  239. data/lib/active_record/relation/predicate_builder.rb +79 -53
  240. data/lib/active_record/relation/query_attribute.rb +30 -12
  241. data/lib/active_record/relation/query_methods.rb +1156 -279
  242. data/lib/active_record/relation/record_fetch_warning.rb +12 -11
  243. data/lib/active_record/relation/spawn_methods.rb +10 -9
  244. data/lib/active_record/relation/where_clause.rb +100 -66
  245. data/lib/active_record/relation.rb +829 -194
  246. data/lib/active_record/result.rb +76 -56
  247. data/lib/active_record/runtime_registry.rb +71 -13
  248. data/lib/active_record/sanitization.rb +86 -47
  249. data/lib/active_record/schema.rb +39 -23
  250. data/lib/active_record/schema_dumper.rb +140 -33
  251. data/lib/active_record/schema_migration.rb +74 -29
  252. data/lib/active_record/scoping/default.rb +73 -19
  253. data/lib/active_record/scoping/named.rb +10 -28
  254. data/lib/active_record/scoping.rb +65 -35
  255. data/lib/active_record/secure_password.rb +60 -0
  256. data/lib/active_record/secure_token.rb +34 -8
  257. data/lib/active_record/serialization.rb +11 -4
  258. data/lib/active_record/signed_id.rb +138 -0
  259. data/lib/active_record/statement_cache.rb +26 -10
  260. data/lib/active_record/store.rb +19 -14
  261. data/lib/active_record/suppressor.rb +15 -17
  262. data/lib/active_record/table_metadata.rb +46 -36
  263. data/lib/active_record/tasks/database_tasks.rb +371 -205
  264. data/lib/active_record/tasks/mysql_database_tasks.rb +43 -36
  265. data/lib/active_record/tasks/postgresql_database_tasks.rb +54 -41
  266. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -13
  267. data/lib/active_record/test_databases.rb +5 -4
  268. data/lib/active_record/test_fixtures.rb +189 -104
  269. data/lib/active_record/testing/query_assertions.rb +121 -0
  270. data/lib/active_record/timestamp.rb +35 -25
  271. data/lib/active_record/token_for.rb +123 -0
  272. data/lib/active_record/touch_later.rb +31 -27
  273. data/lib/active_record/transaction.rb +132 -0
  274. data/lib/active_record/transactions.rb +131 -99
  275. data/lib/active_record/translation.rb +3 -5
  276. data/lib/active_record/type/adapter_specific_registry.rb +33 -18
  277. data/lib/active_record/type/hash_lookup_type_map.rb +34 -2
  278. data/lib/active_record/type/internal/timezone.rb +7 -2
  279. data/lib/active_record/type/serialized.rb +11 -6
  280. data/lib/active_record/type/time.rb +14 -0
  281. data/lib/active_record/type/type_map.rb +17 -21
  282. data/lib/active_record/type/unsigned_integer.rb +0 -1
  283. data/lib/active_record/type.rb +7 -2
  284. data/lib/active_record/type_caster/connection.rb +4 -5
  285. data/lib/active_record/type_caster/map.rb +8 -5
  286. data/lib/active_record/validations/absence.rb +1 -1
  287. data/lib/active_record/validations/associated.rb +13 -8
  288. data/lib/active_record/validations/numericality.rb +36 -0
  289. data/lib/active_record/validations/presence.rb +5 -28
  290. data/lib/active_record/validations/uniqueness.rb +88 -18
  291. data/lib/active_record/validations.rb +15 -8
  292. data/lib/active_record/version.rb +1 -1
  293. data/lib/active_record.rb +446 -40
  294. data/lib/arel/alias_predication.rb +1 -1
  295. data/lib/arel/attributes/attribute.rb +4 -8
  296. data/lib/arel/collectors/bind.rb +8 -1
  297. data/lib/arel/collectors/composite.rb +15 -0
  298. data/lib/arel/collectors/sql_string.rb +7 -0
  299. data/lib/arel/collectors/substitute_binds.rb +7 -0
  300. data/lib/arel/crud.rb +30 -22
  301. data/lib/arel/delete_manager.rb +23 -4
  302. data/lib/arel/errors.rb +10 -0
  303. data/lib/arel/factory_methods.rb +4 -0
  304. data/lib/arel/filter_predications.rb +9 -0
  305. data/lib/arel/insert_manager.rb +2 -3
  306. data/lib/arel/nodes/binary.rb +82 -9
  307. data/lib/arel/nodes/bind_param.rb +8 -0
  308. data/lib/arel/nodes/bound_sql_literal.rb +65 -0
  309. data/lib/arel/nodes/casted.rb +22 -10
  310. data/lib/arel/nodes/cte.rb +36 -0
  311. data/lib/arel/nodes/delete_statement.rb +14 -13
  312. data/lib/arel/nodes/equality.rb +6 -9
  313. data/lib/arel/nodes/filter.rb +10 -0
  314. data/lib/arel/nodes/fragments.rb +35 -0
  315. data/lib/arel/nodes/function.rb +1 -0
  316. data/lib/arel/nodes/grouping.rb +3 -0
  317. data/lib/arel/nodes/homogeneous_in.rb +68 -0
  318. data/lib/arel/nodes/in.rb +8 -1
  319. data/lib/arel/nodes/infix_operation.rb +13 -1
  320. data/lib/arel/nodes/insert_statement.rb +2 -2
  321. data/lib/arel/nodes/join_source.rb +1 -1
  322. data/lib/arel/nodes/leading_join.rb +8 -0
  323. data/lib/arel/nodes/{and.rb → nary.rb} +9 -2
  324. data/lib/arel/nodes/node.rb +122 -11
  325. data/lib/arel/nodes/ordering.rb +27 -0
  326. data/lib/arel/nodes/select_core.rb +2 -2
  327. data/lib/arel/nodes/select_statement.rb +2 -2
  328. data/lib/arel/nodes/sql_literal.rb +16 -0
  329. data/lib/arel/nodes/table_alias.rb +11 -3
  330. data/lib/arel/nodes/unary.rb +0 -1
  331. data/lib/arel/nodes/update_statement.rb +11 -4
  332. data/lib/arel/nodes.rb +10 -3
  333. data/lib/arel/predications.rb +31 -28
  334. data/lib/arel/select_manager.rb +18 -9
  335. data/lib/arel/table.rb +21 -10
  336. data/lib/arel/tree_manager.rb +8 -15
  337. data/lib/arel/update_manager.rb +25 -5
  338. data/lib/arel/visitors/dot.rb +94 -90
  339. data/lib/arel/visitors/mysql.rb +34 -6
  340. data/lib/arel/visitors/postgresql.rb +5 -16
  341. data/lib/arel/visitors/sqlite.rb +25 -1
  342. data/lib/arel/visitors/to_sql.rb +227 -81
  343. data/lib/arel/visitors/visitor.rb +2 -3
  344. data/lib/arel/visitors.rb +0 -7
  345. data/lib/arel.rb +37 -15
  346. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  347. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  348. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  349. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  350. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +6 -1
  351. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
  352. data/lib/rails/generators/active_record/migration.rb +9 -3
  353. data/lib/rails/generators/active_record/model/USAGE +113 -0
  354. data/lib/rails/generators/active_record/model/model_generator.rb +49 -4
  355. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  356. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  357. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  358. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  359. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  360. metadata +117 -30
  361. data/lib/active_record/attribute_decorators.rb +0 -90
  362. data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
  363. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  364. data/lib/active_record/define_callbacks.rb +0 -22
  365. data/lib/active_record/null_relation.rb +0 -68
  366. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  367. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  368. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  369. data/lib/arel/attributes.rb +0 -22
  370. data/lib/arel/visitors/depth_first.rb +0 -204
  371. data/lib/arel/visitors/ibm_db.rb +0 -34
  372. data/lib/arel/visitors/informix.rb +0 -62
  373. data/lib/arel/visitors/mssql.rb +0 -157
  374. data/lib/arel/visitors/oracle.rb +0 -159
  375. data/lib/arel/visitors/oracle12.rb +0 -66
  376. data/lib/arel/visitors/where_sql.rb +0 -23
@@ -1,14 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_record"
4
+ require "active_support/configuration_file"
5
+ require "active_support/deprecation"
4
6
 
5
7
  databases = ActiveRecord::Tasks::DatabaseTasks.setup_initial_database_yaml
6
8
 
7
9
  db_namespace = namespace :db do
8
10
  desc "Set the environment value for the database"
9
11
  task "environment:set" => :load_config do
10
- ActiveRecord::InternalMetadata.create_table
11
- ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Base.connection.migration_context.current_environment
12
+ pool = ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool
13
+ raise ActiveRecord::EnvironmentStorageError unless pool.internal_metadata.enabled?
14
+
15
+ pool.internal_metadata.create_table_and_set_flags(pool.migration_context.current_environment)
12
16
  end
13
17
 
14
18
  task check_protected_environments: :load_config do
@@ -16,7 +20,10 @@ db_namespace = namespace :db do
16
20
  end
17
21
 
18
22
  task load_config: :environment do
19
- ActiveRecord::Base.configurations = ActiveRecord::Tasks::DatabaseTasks.database_configuration || {}
23
+ if ActiveRecord::Base.configurations.empty?
24
+ ActiveRecord::Base.configurations = ActiveRecord::Tasks::DatabaseTasks.database_configuration
25
+ end
26
+
20
27
  ActiveRecord::Migrator.migrations_paths = ActiveRecord::Tasks::DatabaseTasks.migrations_paths
21
28
  end
22
29
 
@@ -25,16 +32,16 @@ db_namespace = namespace :db do
25
32
  ActiveRecord::Tasks::DatabaseTasks.create_all
26
33
  end
27
34
 
28
- ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name|
29
- desc "Create #{spec_name} database for current environment"
30
- task spec_name => :load_config do
31
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name)
32
- ActiveRecord::Tasks::DatabaseTasks.create(db_config.config)
35
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
36
+ desc "Create #{name} database for current environment"
37
+ task name => :load_config do
38
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: name)
39
+ ActiveRecord::Tasks::DatabaseTasks.create(db_config)
33
40
  end
34
41
  end
35
42
  end
36
43
 
37
- desc "Creates the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:create:all to create all databases in the config). Without RAILS_ENV or when RAILS_ENV is development, it defaults to creating the development and test databases."
44
+ desc "Create the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:create:all to create all databases in the config). Without RAILS_ENV or when RAILS_ENV is development, it defaults to creating the development and test databases, except when DATABASE_URL is present."
38
45
  task create: [:load_config] do
39
46
  ActiveRecord::Tasks::DatabaseTasks.create_current
40
47
  end
@@ -44,16 +51,16 @@ db_namespace = namespace :db do
44
51
  ActiveRecord::Tasks::DatabaseTasks.drop_all
45
52
  end
46
53
 
47
- ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name|
48
- desc "Drop #{spec_name} database for current environment"
49
- task spec_name => [:load_config, :check_protected_environments] do
50
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name)
51
- ActiveRecord::Tasks::DatabaseTasks.drop(db_config.config)
54
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
55
+ desc "Drop #{name} database for current environment"
56
+ task name => [:load_config, :check_protected_environments] do
57
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: name)
58
+ ActiveRecord::Tasks::DatabaseTasks.drop(db_config)
52
59
  end
53
60
  end
54
61
  end
55
62
 
56
- desc "Drops the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:drop:all to drop all databases in the config). Without RAILS_ENV or when RAILS_ENV is development, it defaults to dropping the development and test databases."
63
+ desc "Drop the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:drop:all to drop all databases in the config). Without RAILS_ENV or when RAILS_ENV is development, it defaults to dropping the development and test databases, except when DATABASE_URL is present."
57
64
  task drop: [:load_config, :check_protected_environments] do
58
65
  db_namespace["drop:_unsafe"].invoke
59
66
  end
@@ -73,47 +80,73 @@ db_namespace = namespace :db do
73
80
  ActiveRecord::Tasks::DatabaseTasks.truncate_all
74
81
  end
75
82
 
76
- # desc "Empty the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:purge:all to purge all databases in the config). Without RAILS_ENV it defaults to purging the development and test databases."
83
+ # desc "Empty the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:purge:all to purge all databases in the config). Without RAILS_ENV it defaults to purging the development and test databases, except when DATABASE_URL is present."
77
84
  task purge: [:load_config, :check_protected_environments] do
78
85
  ActiveRecord::Tasks::DatabaseTasks.purge_current
79
86
  end
80
87
 
81
88
  desc "Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)."
82
89
  task migrate: :load_config do
83
- ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
84
- ActiveRecord::Base.establish_connection(db_config.config)
90
+ db_configs = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env)
91
+
92
+ if db_configs.size == 1 && db_configs.first.primary?
85
93
  ActiveRecord::Tasks::DatabaseTasks.migrate
94
+ else
95
+ mapped_versions = ActiveRecord::Tasks::DatabaseTasks.db_configs_with_versions
96
+
97
+ mapped_versions.sort.each do |version, db_configs|
98
+ db_configs.each do |db_config|
99
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection(db_config) do
100
+ ActiveRecord::Tasks::DatabaseTasks.migrate(version)
101
+ end
102
+ end
103
+ end
86
104
  end
105
+
87
106
  db_namespace["_dump"].invoke
88
107
  end
89
108
 
90
- # IMPORTANT: This task won't dump the schema if ActiveRecord::Base.dump_schema_after_migration is set to false
109
+ # IMPORTANT: This task won't dump the schema if ActiveRecord.dump_schema_after_migration is set to false
91
110
  task :_dump do
92
- if ActiveRecord::Base.dump_schema_after_migration
93
- case ActiveRecord::Base.schema_format
94
- when :ruby then db_namespace["schema:dump"].invoke
95
- when :sql then db_namespace["structure:dump"].invoke
96
- else
97
- raise "unknown schema format #{ActiveRecord::Base.schema_format}"
98
- end
111
+ if ActiveRecord.dump_schema_after_migration
112
+ db_namespace["schema:dump"].invoke
99
113
  end
100
114
  # Allow this task to be called as many times as required. An example is the
101
115
  # migrate:redo task, which calls other two internally that depend on this one.
102
116
  db_namespace["_dump"].reenable
103
117
  end
104
118
 
119
+ namespace :_dump do
120
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
121
+ # IMPORTANT: This task won't dump the schema if ActiveRecord.dump_schema_after_migration is set to false
122
+ task name do
123
+ if ActiveRecord.dump_schema_after_migration
124
+ db_namespace["schema:dump:#{name}"].invoke
125
+ end
126
+
127
+ # Allow this task to be called as many times as required. An example is the
128
+ # migrate:redo task, which calls other two internally that depend on this one.
129
+ db_namespace["_dump:#{name}"].reenable
130
+ end
131
+ end
132
+ end
133
+
105
134
  namespace :migrate do
106
- ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name|
107
- desc "Migrate #{spec_name} database for current environment"
108
- task spec_name => :load_config do
109
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name)
110
- ActiveRecord::Base.establish_connection(db_config.config)
111
- ActiveRecord::Tasks::DatabaseTasks.migrate
135
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
136
+ desc "Migrate #{name} database for current environment"
137
+ task name => :load_config do
138
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: Rails.env, name: name) do
139
+ ActiveRecord::Tasks::DatabaseTasks.migrate
140
+ end
141
+
142
+ db_namespace["_dump:#{name}"].invoke
112
143
  end
113
144
  end
114
145
 
115
- # desc 'Rollbacks the database one migration and re migrate up (options: STEP=x, VERSION=x).'
146
+ desc "Roll back the database one migration and re-migrate up (options: STEP=x, VERSION=x)."
116
147
  task redo: :load_config do
148
+ ActiveRecord::Tasks::DatabaseTasks.raise_for_multi_db(command: "db:migrate:redo")
149
+
117
150
  raise "Empty VERSION provided" if ENV["VERSION"] && ENV["VERSION"].empty?
118
151
 
119
152
  if ENV["VERSION"]
@@ -125,10 +158,27 @@ db_namespace = namespace :db do
125
158
  end
126
159
  end
127
160
 
161
+ namespace :redo do
162
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
163
+ desc "Roll back #{name} database one migration and re-migrate up (options: STEP=x, VERSION=x)."
164
+ task name => :load_config do
165
+ raise "Empty VERSION provided" if ENV["VERSION"] && ENV["VERSION"].empty?
166
+
167
+ if ENV["VERSION"]
168
+ db_namespace["migrate:down:#{name}"].invoke
169
+ db_namespace["migrate:up:#{name}"].invoke
170
+ else
171
+ db_namespace["rollback:#{name}"].invoke
172
+ db_namespace["migrate:#{name}"].invoke
173
+ end
174
+ end
175
+ end
176
+ end
177
+
128
178
  # desc 'Resets your database using your migrations for the current environment'
129
179
  task reset: ["db:drop", "db:create", "db:migrate"]
130
180
 
131
- # desc 'Runs the "up" for a given migration VERSION.'
181
+ desc 'Run the "up" for a given migration VERSION.'
132
182
  task up: :load_config do
133
183
  ActiveRecord::Tasks::DatabaseTasks.raise_for_multi_db(command: "db:migrate:up")
134
184
 
@@ -136,7 +186,7 @@ db_namespace = namespace :db do
136
186
 
137
187
  ActiveRecord::Tasks::DatabaseTasks.check_target_version
138
188
 
139
- ActiveRecord::Base.connection.migration_context.run(
189
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool.migration_context.run(
140
190
  :up,
141
191
  ActiveRecord::Tasks::DatabaseTasks.target_version
142
192
  )
@@ -144,25 +194,22 @@ db_namespace = namespace :db do
144
194
  end
145
195
 
146
196
  namespace :up do
147
- ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name|
148
- task spec_name => :load_config do
197
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
198
+ desc "Run the \"up\" on #{name} database for a given migration VERSION."
199
+ task name => :load_config do
149
200
  raise "VERSION is required" if !ENV["VERSION"] || ENV["VERSION"].empty?
150
201
 
151
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name)
152
-
153
- ActiveRecord::Base.establish_connection(db_config.config)
154
- ActiveRecord::Tasks::DatabaseTasks.check_target_version
155
- ActiveRecord::Base.connection.migration_context.run(
156
- :up,
157
- ActiveRecord::Tasks::DatabaseTasks.target_version
158
- )
202
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: Rails.env, name: name) do |pool|
203
+ ActiveRecord::Tasks::DatabaseTasks.check_target_version
204
+ pool.migration_context.run(:up, ActiveRecord::Tasks::DatabaseTasks.target_version)
205
+ end
159
206
 
160
- db_namespace["_dump"].invoke
207
+ db_namespace["_dump:#{name}"].invoke
161
208
  end
162
209
  end
163
210
  end
164
211
 
165
- # desc 'Runs the "down" for a given migration VERSION.'
212
+ desc 'Run the "down" for a given migration VERSION.'
166
213
  task down: :load_config do
167
214
  ActiveRecord::Tasks::DatabaseTasks.raise_for_multi_db(command: "db:migrate:down")
168
215
 
@@ -170,7 +217,7 @@ db_namespace = namespace :db do
170
217
 
171
218
  ActiveRecord::Tasks::DatabaseTasks.check_target_version
172
219
 
173
- ActiveRecord::Base.connection.migration_context.run(
220
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool.migration_context.run(
174
221
  :down,
175
222
  ActiveRecord::Tasks::DatabaseTasks.target_version
176
223
  )
@@ -178,163 +225,193 @@ db_namespace = namespace :db do
178
225
  end
179
226
 
180
227
  namespace :down do
181
- ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name|
182
- task spec_name => :load_config do
228
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
229
+ desc "Run the \"down\" on #{name} database for a given migration VERSION."
230
+ task name => :load_config do
183
231
  raise "VERSION is required" if !ENV["VERSION"] || ENV["VERSION"].empty?
184
232
 
185
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name)
186
-
187
- ActiveRecord::Base.establish_connection(db_config.config)
188
- ActiveRecord::Tasks::DatabaseTasks.check_target_version
189
- ActiveRecord::Base.connection.migration_context.run(
190
- :down,
191
- ActiveRecord::Tasks::DatabaseTasks.target_version
192
- )
233
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: Rails.env, name: name) do |pool|
234
+ ActiveRecord::Tasks::DatabaseTasks.check_target_version
235
+ pool.migration_context.run(:down, ActiveRecord::Tasks::DatabaseTasks.target_version)
236
+ end
193
237
 
194
- db_namespace["_dump"].invoke
238
+ db_namespace["_dump:#{name}"].invoke
195
239
  end
196
240
  end
197
241
  end
198
242
 
199
243
  desc "Display status of migrations"
200
244
  task status: :load_config do
201
- ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
202
- ActiveRecord::Base.establish_connection(db_config.config)
245
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each do
203
246
  ActiveRecord::Tasks::DatabaseTasks.migrate_status
204
247
  end
205
248
  end
206
249
 
207
250
  namespace :status do
208
- ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name|
209
- desc "Display status of migrations for #{spec_name} database"
210
- task spec_name => :load_config do
211
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name)
212
- ActiveRecord::Base.establish_connection(db_config.config)
213
- ActiveRecord::Tasks::DatabaseTasks.migrate_status
251
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
252
+ desc "Display status of migrations for #{name} database"
253
+ task name => :load_config do
254
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: Rails.env, name: name) do
255
+ ActiveRecord::Tasks::DatabaseTasks.migrate_status
256
+ end
214
257
  end
215
258
  end
216
259
  end
217
260
  end
218
261
 
219
- desc "Rolls the schema back to the previous version (specify steps w/ STEP=n)."
262
+ namespace :rollback do
263
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
264
+ desc "Rollback #{name} database for current environment (specify steps w/ STEP=n)."
265
+ task name => :load_config do
266
+ step = ENV["STEP"] ? ENV["STEP"].to_i : 1
267
+
268
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: Rails.env, name: name) do |pool|
269
+ pool.migration_context.rollback(step)
270
+ end
271
+
272
+ db_namespace["_dump:#{name}"].invoke
273
+ end
274
+ end
275
+ end
276
+
277
+ desc "Roll the schema back to the previous version (specify steps w/ STEP=n)."
220
278
  task rollback: :load_config do
279
+ ActiveRecord::Tasks::DatabaseTasks.raise_for_multi_db(command: "db:rollback")
280
+ raise "VERSION is not supported - To rollback a specific version, use db:migrate:down" if ENV["VERSION"]
281
+
221
282
  step = ENV["STEP"] ? ENV["STEP"].to_i : 1
222
- ActiveRecord::Base.connection.migration_context.rollback(step)
283
+
284
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool.migration_context.rollback(step)
285
+
223
286
  db_namespace["_dump"].invoke
224
287
  end
225
288
 
226
289
  # desc 'Pushes the schema to the next version (specify steps w/ STEP=n).'
227
290
  task forward: :load_config do
228
291
  step = ENV["STEP"] ? ENV["STEP"].to_i : 1
229
- ActiveRecord::Base.connection.migration_context.forward(step)
292
+
293
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool.migration_context.forward(step)
294
+
230
295
  db_namespace["_dump"].invoke
231
296
  end
232
297
 
233
- # desc 'Drops and recreates the database from db/schema.rb for the current environment and loads the seeds.'
298
+ namespace :reset do
299
+ task all: ["db:drop", "db:setup"]
300
+
301
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
302
+ desc "Drop and recreate the #{name} database from its schema for the current environment and load the seeds."
303
+ task name => ["db:drop:#{name}", "db:setup:#{name}"]
304
+ end
305
+ end
306
+
307
+ desc "Drop and recreate all databases from their schema for the current environment and load the seeds."
234
308
  task reset: [ "db:drop", "db:setup" ]
235
309
 
236
- # desc "Retrieves the charset for the current environment's database"
310
+ # desc "Retrieve the charset for the current environment's database"
237
311
  task charset: :load_config do
238
312
  puts ActiveRecord::Tasks::DatabaseTasks.charset_current
239
313
  end
240
314
 
241
- # desc "Retrieves the collation for the current environment's database"
315
+ # desc "Retrieve the collation for the current environment's database"
242
316
  task collation: :load_config do
243
317
  puts ActiveRecord::Tasks::DatabaseTasks.collation_current
244
318
  rescue NoMethodError
245
319
  $stderr.puts "Sorry, your database adapter is not supported yet. Feel free to submit a patch."
246
320
  end
247
321
 
248
- desc "Retrieves the current schema version number"
322
+ desc "Retrieve the current schema version number"
249
323
  task version: :load_config do
250
- puts "Current version: #{ActiveRecord::Base.connection.migration_context.current_version}"
324
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: Rails.env) do |pool|
325
+ puts "\ndatabase: #{pool.db_config.database}\n"
326
+ puts "Current version: #{pool.migration_context.current_version}"
327
+ puts
328
+ end
329
+ end
330
+
331
+ namespace :version do
332
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
333
+ desc "Retrieve the current schema version number for #{name} database"
334
+ task name => :load_config do
335
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: name)
336
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection(db_config) do |connection|
337
+ puts "Current version: #{connection.schema_version}"
338
+ end
339
+ end
340
+ end
251
341
  end
252
342
 
253
343
  # desc "Raises an error if there are pending migrations"
254
344
  task abort_if_pending_migrations: :load_config do
255
- pending_migrations = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).flat_map do |db_config|
256
- ActiveRecord::Base.establish_connection(db_config.config)
345
+ pending_migrations = []
257
346
 
258
- ActiveRecord::Base.connection.migration_context.open.pending_migrations
347
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each do |pool|
348
+ pending_migrations << pool.migration_context.open.pending_migrations
259
349
  end
260
350
 
351
+ pending_migrations = pending_migrations.flatten!
352
+
261
353
  if pending_migrations.any?
262
354
  puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}"
355
+
263
356
  pending_migrations.each do |pending_migration|
264
357
  puts " %4d %s" % [pending_migration.version, pending_migration.name]
265
358
  end
266
- abort %{Run `rails db:migrate` to update your database then try again.}
359
+
360
+ abort %{Run `bin/rails db:migrate` to update your database then try again.}
267
361
  end
268
- ensure
269
- ActiveRecord::Base.establish_connection(ActiveRecord::Tasks::DatabaseTasks.env.to_sym)
270
362
  end
271
363
 
272
364
  namespace :abort_if_pending_migrations do
273
- ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name|
274
- # desc "Raises an error if there are pending migrations for #{spec_name} database"
275
- task spec_name => :load_config do
276
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name)
277
- ActiveRecord::Base.establish_connection(db_config.config)
278
-
279
- pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations
280
-
281
- if pending_migrations.any?
282
- puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}"
283
- pending_migrations.each do |pending_migration|
284
- puts " %4d %s" % [pending_migration.version, pending_migration.name]
365
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
366
+ # desc "Raise an error if there are pending migrations for #{name} database"
367
+ task name => :load_config do
368
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: Rails.env, name: name) do |pool|
369
+ pending_migrations = pool.migration_context.open.pending_migrations
370
+
371
+ if pending_migrations.any?
372
+ puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}"
373
+
374
+ pending_migrations.each do |pending_migration|
375
+ puts " %4d %s" % [pending_migration.version, pending_migration.name]
376
+ end
377
+
378
+ abort %{Run `bin/rails db:migrate:#{name}` to update your database then try again.}
285
379
  end
286
- abort %{Run `rails db:migrate:#{spec_name}` to update your database then try again.}
287
380
  end
288
381
  end
289
382
  end
290
383
  end
291
384
 
292
- desc "Creates the database, loads the schema, and initializes with the seed data (use db:reset to also drop the database first)"
293
- task setup: ["db:schema:load_if_ruby", "db:structure:load_if_sql", :seed]
294
-
295
- desc "Runs setup if database does not exist, or runs migrations if it does"
296
- task prepare: :load_config do
297
- seed = false
298
-
299
- ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
300
- ActiveRecord::Base.establish_connection(db_config.config)
385
+ namespace :setup do
386
+ task all: ["db:create", :environment, "db:schema:load", :seed]
301
387
 
302
- # Skipped when no database
303
- ActiveRecord::Tasks::DatabaseTasks.migrate
304
- if ActiveRecord::Base.dump_schema_after_migration
305
- ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config.config, ActiveRecord::Base.schema_format, db_config.spec_name)
306
- end
307
-
308
- rescue ActiveRecord::NoDatabaseError
309
- ActiveRecord::Tasks::DatabaseTasks.create_current(db_config.env_name, db_config.spec_name)
310
- ActiveRecord::Tasks::DatabaseTasks.load_schema(
311
- db_config.config,
312
- ActiveRecord::Base.schema_format,
313
- nil,
314
- db_config.env_name,
315
- db_config.spec_name
316
- )
317
-
318
- seed = true
388
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
389
+ desc "Create the #{name} database, load the schema, and initialize with the seed data (use db:reset:#{name} to also drop the database first)"
390
+ task name => ["db:create:#{name}", :environment, "db:schema:load:#{name}", "db:seed"]
319
391
  end
392
+ end
320
393
 
321
- ActiveRecord::Base.establish_connection
322
- ActiveRecord::Tasks::DatabaseTasks.load_seed if seed
394
+ desc "Create all databases, load all schemas, and initialize with the seed data (use db:reset to also drop all databases first)"
395
+ task setup: ["db:create", :environment, "db:schema:load", :seed]
396
+
397
+ desc "Run setup if database does not exist, or run migrations if it does"
398
+ task prepare: :load_config do
399
+ ActiveRecord::Tasks::DatabaseTasks.prepare_all
323
400
  end
324
401
 
325
- desc "Loads the seed data from db/seeds.rb"
402
+ desc "Load the seed data from db/seeds.rb"
326
403
  task seed: :load_config do
327
404
  db_namespace["abort_if_pending_migrations"].invoke
328
405
  ActiveRecord::Tasks::DatabaseTasks.load_seed
329
406
  end
330
407
 
331
408
  namespace :seed do
332
- desc "Truncates tables of each database for current environment and loads the seeds"
409
+ desc "Truncate tables of each database for current environment and load the seeds"
333
410
  task replant: [:load_config, :truncate_all, :seed]
334
411
  end
335
412
 
336
413
  namespace :fixtures do
337
- desc "Loads fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y. Load from subdirectory in test/fixtures using FIXTURES_DIR=z. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures."
414
+ desc "Load fixtures into the current environment's database. To load specific fixtures, use FIXTURES=x,y. To load from subdirectory in test/fixtures, use FIXTURES_DIR=z. To specify an alternative path (e.g. spec/fixtures), use FIXTURES_PATH=spec/fixtures."
338
415
  task load: :load_config do
339
416
  require "active_record/fixtures"
340
417
 
@@ -349,14 +426,15 @@ db_namespace = namespace :db do
349
426
  fixture_files = if ENV["FIXTURES"]
350
427
  ENV["FIXTURES"].split(",")
351
428
  else
352
- # The use of String#[] here is to support namespaced fixtures.
353
- Dir["#{fixtures_dir}/**/*.yml"].map { |f| f[(fixtures_dir.size + 1)..-5] }
429
+ files = Dir[File.join(fixtures_dir, "**/*.{yml}")]
430
+ files.reject! { |f| f.start_with?(File.join(fixtures_dir, "files")) }
431
+ files.map! { |f| f[fixtures_dir.to_s.size..-5].delete_prefix("/") }
354
432
  end
355
433
 
356
434
  ActiveRecord::FixtureSet.create_fixtures(fixtures_dir, fixture_files)
357
435
  end
358
436
 
359
- # desc "Search for a fixture given a LABEL or ID. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures."
437
+ # desc "Search for a fixture given a LABEL or ID. Specify an alternative path (e.g. spec/fixtures) using FIXTURES_PATH=spec/fixtures."
360
438
  task identify: :load_config do
361
439
  require "active_record/fixtures"
362
440
 
@@ -368,7 +446,7 @@ db_namespace = namespace :db do
368
446
  base_dir = ActiveRecord::Tasks::DatabaseTasks.fixtures_path
369
447
 
370
448
  Dir["#{base_dir}/**/*.yml"].each do |file|
371
- if data = YAML.load(ERB.new(IO.read(file)).result)
449
+ if data = ActiveSupport::ConfigurationFile.parse(file)
372
450
  data.each_key do |key|
373
451
  key_id = ActiveRecord::FixtureSet.identify(key)
374
452
 
@@ -382,113 +460,141 @@ db_namespace = namespace :db do
382
460
  end
383
461
 
384
462
  namespace :schema do
385
- desc "Creates a db/schema.rb file that is portable against any DB supported by Active Record"
463
+ desc "Create a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`)"
386
464
  task dump: :load_config do
387
- ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
388
- ActiveRecord::Base.establish_connection(db_config.config)
389
- ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config.config, :ruby, db_config.spec_name)
465
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each do |pool|
466
+ db_config = pool.db_config
467
+ schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
468
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, schema_format)
390
469
  end
391
470
 
392
471
  db_namespace["schema:dump"].reenable
393
472
  end
394
473
 
395
- desc "Loads a schema.rb file into the database"
474
+ desc "Load a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`) into the database"
396
475
  task load: [:load_config, :check_protected_environments] do
397
- ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:ruby, ENV["SCHEMA"])
476
+ schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
477
+ ActiveRecord::Tasks::DatabaseTasks.load_schema_current(schema_format, ENV["SCHEMA"])
478
+ end
479
+
480
+ namespace :dump do
481
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
482
+ desc "Create a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`) for #{name} database"
483
+ task name => :load_config do
484
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(name: name) do |pool|
485
+ db_config = pool.db_config
486
+ schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
487
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, schema_format)
488
+ end
489
+
490
+ db_namespace["schema:dump:#{name}"].reenable
491
+ end
492
+ end
398
493
  end
399
494
 
400
- task load_if_ruby: ["db:create", :environment] do
401
- db_namespace["schema:load"].invoke if ActiveRecord::Base.schema_format == :ruby
495
+ namespace :load do
496
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
497
+ desc "Load a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`) into the #{name} database"
498
+ task name => "db:test:purge:#{name}" do
499
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(name: name) do |pool|
500
+ db_config = pool.db_config
501
+ schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
502
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
503
+ end
504
+ end
505
+ end
402
506
  end
403
507
 
404
508
  namespace :cache do
405
- desc "Creates a db/schema_cache.yml file."
509
+ desc "Create a db/schema_cache.yml file."
406
510
  task dump: :load_config do
407
- ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
408
- ActiveRecord::Base.establish_connection(db_config.config)
409
- filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(db_config.spec_name)
410
- ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(
411
- ActiveRecord::Base.connection,
412
- filename,
413
- )
511
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each do |pool|
512
+ db_config = pool.db_config
513
+ filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(db_config)
514
+
515
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(pool, filename)
414
516
  end
415
517
  end
416
518
 
417
- desc "Clears a db/schema_cache.yml file."
519
+ desc "Clear a db/schema_cache.yml file."
418
520
  task clear: :load_config do
419
521
  ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
420
- filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(db_config.spec_name)
421
- rm_f filename, verbose: false
522
+ filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(db_config)
523
+ ActiveRecord::Tasks::DatabaseTasks.clear_schema_cache(
524
+ filename,
525
+ )
422
526
  end
423
527
  end
424
528
  end
425
529
  end
426
530
 
427
- namespace :structure do
428
- desc "Dumps the database structure to db/structure.sql. Specify another file with SCHEMA=db/my_structure.sql"
429
- task dump: :load_config do
430
- ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
431
- ActiveRecord::Base.establish_connection(db_config.config)
432
- ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config.config, :sql, db_config.spec_name)
433
- end
434
-
435
- db_namespace["structure:dump"].reenable
436
- end
437
-
438
- desc "Recreates the databases from the structure.sql file"
439
- task load: [:load_config, :check_protected_environments] do
440
- ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:sql, ENV["SCHEMA"])
441
- end
531
+ namespace :encryption do
532
+ desc "Generate a set of keys for configuring Active Record encryption in a given environment"
533
+ task :init do
534
+ puts <<~MSG
535
+ Add this entry to the credentials of the target environment:#{' '}
442
536
 
443
- task load_if_sql: ["db:create", :environment] do
444
- db_namespace["structure:load"].invoke if ActiveRecord::Base.schema_format == :sql
537
+ active_record_encryption:
538
+ primary_key: #{SecureRandom.alphanumeric(32)}
539
+ deterministic_key: #{SecureRandom.alphanumeric(32)}
540
+ key_derivation_salt: #{SecureRandom.alphanumeric(32)}
541
+ MSG
445
542
  end
446
543
  end
447
544
 
448
545
  namespace :test do
449
- # desc "Recreate the test database from the current schema"
450
- task load: %w(db:test:purge) do
451
- case ActiveRecord::Base.schema_format
452
- when :ruby
453
- db_namespace["test:load_schema"].invoke
454
- when :sql
455
- db_namespace["test:load_structure"].invoke
456
- end
457
- end
458
-
459
- # desc "Recreate the test database from an existent schema.rb file"
546
+ # desc "Recreate the test database from an existent schema file (schema.rb or structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`)"
460
547
  task load_schema: %w(db:test:purge) do
461
- should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
462
- ActiveRecord::Schema.verbose = false
463
- ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
464
- filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(db_config.spec_name, :ruby)
465
- ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config.config, :ruby, filename, "test")
466
- end
467
- ensure
468
- if should_reconnect
469
- ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations.default_hash(ActiveRecord::Tasks::DatabaseTasks.env))
470
- end
471
- end
472
-
473
- # desc "Recreate the test database from an existent structure.sql file"
474
- task load_structure: %w(db:test:purge) do
475
- ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
476
- filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(db_config.spec_name, :sql)
477
- ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config.config, :sql, filename, "test")
548
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: "test") do |pool|
549
+ db_config = pool.db_config
550
+ ActiveRecord::Schema.verbose = false
551
+ schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
552
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
478
553
  end
479
554
  end
480
555
 
481
556
  # desc "Empty the test database"
482
557
  task purge: %w(load_config check_protected_environments) do
483
558
  ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
484
- ActiveRecord::Tasks::DatabaseTasks.purge(db_config.config)
559
+ ActiveRecord::Tasks::DatabaseTasks.purge(db_config)
485
560
  end
486
561
  end
487
562
 
488
563
  # desc 'Load the test schema'
489
564
  task prepare: :load_config do
490
565
  unless ActiveRecord::Base.configurations.blank?
491
- db_namespace["test:load"].invoke
566
+ db_namespace["test:load_schema"].invoke
567
+ end
568
+ end
569
+
570
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
571
+ # desc "Recreate the #{name} test database from an existent schema.rb file"
572
+ namespace :load_schema do
573
+ task name => "db:test:purge:#{name}" do
574
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: "test", name: name) do |pool|
575
+ db_config = pool.db_config
576
+ ActiveRecord::Schema.verbose = false
577
+ schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
578
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
579
+ end
580
+ end
581
+ end
582
+
583
+ # desc "Empty the #{name} test database"
584
+ namespace :purge do
585
+ task name => %w(load_config check_protected_environments) do
586
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: "test", name: name) do |pool|
587
+ db_config = pool.db_config
588
+ ActiveRecord::Tasks::DatabaseTasks.purge(db_config)
589
+ end
590
+ end
591
+ end
592
+
593
+ # desc 'Load the #{name} database test schema'
594
+ namespace :prepare do
595
+ task name => :load_config do
596
+ db_namespace["test:load_schema:#{name}"].invoke
597
+ end
492
598
  end
493
599
  end
494
600
  end
@@ -496,7 +602,7 @@ end
496
602
 
497
603
  namespace :railties do
498
604
  namespace :install do
499
- # desc "Copies missing migrations from Railties (e.g. engines). You can specify Railties to use with FROM=railtie1,railtie2"
605
+ # desc "Copy missing migrations from Railties (e.g. engines). You can specify Railties to use with FROM=railtie1,railtie2 and database to copy to with DATABASE=database."
500
606
  task migrations: :'db:load_config' do
501
607
  to_load = ENV["FROM"].blank? ? :all : ENV["FROM"].split(",").map(&:strip)
502
608
  railties = {}
@@ -520,7 +626,16 @@ namespace :railties do
520
626
  puts "Copied migration #{migration.basename} from #{name}"
521
627
  end
522
628
 
523
- ActiveRecord::Migration.copy(ActiveRecord::Tasks::DatabaseTasks.migrations_paths.first, railties,
629
+ if ENV["DATABASE"].present? && ENV["DATABASE"] != "primary"
630
+ config = ActiveRecord::Base.configurations.configs_for(name: ENV["DATABASE"])
631
+ raise "Invalid DATABASE provided" if config.blank?
632
+ destination = config.migrations_paths
633
+ raise "#{ENV["DATABASE"]} does not have a custom migration path" if destination.blank?
634
+ else
635
+ destination = ActiveRecord::Tasks::DatabaseTasks.migrations_paths.first
636
+ end
637
+
638
+ ActiveRecord::Migration.copy(destination, railties,
524
639
  on_skip: on_skip, on_copy: on_copy)
525
640
  end
526
641
  end