activerecord 7.0.0 → 7.1.0

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 (249) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1607 -1040
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +17 -18
  5. data/lib/active_record/aggregations.rb +16 -13
  6. data/lib/active_record/association_relation.rb +1 -1
  7. data/lib/active_record/associations/association.rb +18 -3
  8. data/lib/active_record/associations/association_scope.rb +16 -9
  9. data/lib/active_record/associations/belongs_to_association.rb +14 -6
  10. data/lib/active_record/associations/builder/association.rb +3 -3
  11. data/lib/active_record/associations/builder/belongs_to.rb +21 -8
  12. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
  13. data/lib/active_record/associations/builder/singular_association.rb +4 -0
  14. data/lib/active_record/associations/collection_association.rb +17 -12
  15. data/lib/active_record/associations/collection_proxy.rb +22 -12
  16. data/lib/active_record/associations/foreign_association.rb +10 -3
  17. data/lib/active_record/associations/has_many_association.rb +27 -17
  18. data/lib/active_record/associations/has_many_through_association.rb +10 -6
  19. data/lib/active_record/associations/has_one_association.rb +10 -3
  20. data/lib/active_record/associations/join_dependency.rb +20 -14
  21. data/lib/active_record/associations/preloader/association.rb +27 -6
  22. data/lib/active_record/associations/preloader/through_association.rb +1 -1
  23. data/lib/active_record/associations/preloader.rb +13 -10
  24. data/lib/active_record/associations/singular_association.rb +1 -1
  25. data/lib/active_record/associations/through_association.rb +22 -11
  26. data/lib/active_record/associations.rb +345 -219
  27. data/lib/active_record/attribute_assignment.rb +0 -2
  28. data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
  29. data/lib/active_record/attribute_methods/dirty.rb +40 -26
  30. data/lib/active_record/attribute_methods/primary_key.rb +76 -24
  31. data/lib/active_record/attribute_methods/query.rb +28 -16
  32. data/lib/active_record/attribute_methods/read.rb +18 -5
  33. data/lib/active_record/attribute_methods/serialization.rb +172 -69
  34. data/lib/active_record/attribute_methods/write.rb +3 -3
  35. data/lib/active_record/attribute_methods.rb +110 -28
  36. data/lib/active_record/attributes.rb +3 -3
  37. data/lib/active_record/autosave_association.rb +56 -10
  38. data/lib/active_record/base.rb +10 -5
  39. data/lib/active_record/callbacks.rb +16 -32
  40. data/lib/active_record/coders/column_serializer.rb +61 -0
  41. data/lib/active_record/coders/json.rb +1 -1
  42. data/lib/active_record/coders/yaml_column.rb +70 -34
  43. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +164 -89
  44. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
  45. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +3 -1
  46. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +63 -43
  47. data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
  48. data/lib/active_record/connection_adapters/abstract/database_statements.rb +128 -32
  49. data/lib/active_record/connection_adapters/abstract/query_cache.rb +60 -22
  50. data/lib/active_record/connection_adapters/abstract/quoting.rb +52 -8
  51. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  52. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
  53. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +163 -29
  54. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
  55. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +302 -129
  56. data/lib/active_record/connection_adapters/abstract/transaction.rb +287 -58
  57. data/lib/active_record/connection_adapters/abstract_adapter.rb +504 -106
  58. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +217 -104
  59. data/lib/active_record/connection_adapters/column.rb +9 -0
  60. data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
  61. data/lib/active_record/connection_adapters/mysql/database_statements.rb +23 -144
  62. data/lib/active_record/connection_adapters/mysql/quoting.rb +29 -12
  63. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
  64. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
  65. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
  66. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +38 -14
  67. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +148 -0
  68. data/lib/active_record/connection_adapters/mysql2_adapter.rb +98 -53
  69. data/lib/active_record/connection_adapters/pool_config.rb +14 -5
  70. data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
  71. data/lib/active_record/connection_adapters/postgresql/column.rb +3 -2
  72. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +72 -45
  73. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  74. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -2
  75. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
  76. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +3 -1
  77. data/lib/active_record/connection_adapters/postgresql/quoting.rb +41 -8
  78. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +6 -10
  79. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
  80. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +131 -2
  81. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +53 -0
  82. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +358 -57
  83. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
  84. data/lib/active_record/connection_adapters/postgresql_adapter.rb +343 -181
  85. data/lib/active_record/connection_adapters/schema_cache.rb +287 -59
  86. data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
  87. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +45 -39
  88. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +22 -5
  89. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
  90. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +41 -22
  91. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +242 -81
  92. data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
  93. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +98 -0
  94. data/lib/active_record/connection_adapters/trilogy_adapter.rb +254 -0
  95. data/lib/active_record/connection_adapters.rb +3 -1
  96. data/lib/active_record/connection_handling.rb +73 -96
  97. data/lib/active_record/core.rb +136 -148
  98. data/lib/active_record/counter_cache.rb +46 -25
  99. data/lib/active_record/database_configurations/connection_url_resolver.rb +1 -0
  100. data/lib/active_record/database_configurations/database_config.rb +9 -3
  101. data/lib/active_record/database_configurations/hash_config.rb +22 -12
  102. data/lib/active_record/database_configurations/url_config.rb +17 -11
  103. data/lib/active_record/database_configurations.rb +87 -34
  104. data/lib/active_record/delegated_type.rb +9 -4
  105. data/lib/active_record/deprecator.rb +7 -0
  106. data/lib/active_record/destroy_association_async_job.rb +2 -0
  107. data/lib/active_record/disable_joins_association_relation.rb +1 -1
  108. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  109. data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
  110. data/lib/active_record/encryption/config.rb +25 -1
  111. data/lib/active_record/encryption/configurable.rb +13 -14
  112. data/lib/active_record/encryption/context.rb +10 -3
  113. data/lib/active_record/encryption/contexts.rb +8 -4
  114. data/lib/active_record/encryption/derived_secret_key_provider.rb +9 -3
  115. data/lib/active_record/encryption/deterministic_key_provider.rb +1 -1
  116. data/lib/active_record/encryption/encryptable_record.rb +38 -22
  117. data/lib/active_record/encryption/encrypted_attribute_type.rb +19 -8
  118. data/lib/active_record/encryption/encryptor.rb +7 -7
  119. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +3 -3
  120. data/lib/active_record/encryption/extended_deterministic_queries.rb +83 -71
  121. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +3 -3
  122. data/lib/active_record/encryption/key_generator.rb +12 -1
  123. data/lib/active_record/encryption/message.rb +1 -1
  124. data/lib/active_record/encryption/message_serializer.rb +2 -0
  125. data/lib/active_record/encryption/properties.rb +4 -4
  126. data/lib/active_record/encryption/scheme.rb +20 -23
  127. data/lib/active_record/encryption.rb +1 -0
  128. data/lib/active_record/enum.rb +114 -27
  129. data/lib/active_record/errors.rb +108 -15
  130. data/lib/active_record/explain.rb +23 -3
  131. data/lib/active_record/explain_subscriber.rb +1 -1
  132. data/lib/active_record/fixture_set/model_metadata.rb +14 -4
  133. data/lib/active_record/fixture_set/render_context.rb +2 -0
  134. data/lib/active_record/fixture_set/table_row.rb +29 -8
  135. data/lib/active_record/fixtures.rb +121 -73
  136. data/lib/active_record/future_result.rb +30 -5
  137. data/lib/active_record/gem_version.rb +2 -2
  138. data/lib/active_record/inheritance.rb +30 -16
  139. data/lib/active_record/insert_all.rb +55 -8
  140. data/lib/active_record/integration.rb +10 -10
  141. data/lib/active_record/internal_metadata.rb +118 -30
  142. data/lib/active_record/locking/optimistic.rb +32 -18
  143. data/lib/active_record/locking/pessimistic.rb +8 -5
  144. data/lib/active_record/log_subscriber.rb +39 -17
  145. data/lib/active_record/marshalling.rb +56 -0
  146. data/lib/active_record/message_pack.rb +124 -0
  147. data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
  148. data/lib/active_record/middleware/database_selector.rb +18 -13
  149. data/lib/active_record/middleware/shard_selector.rb +7 -5
  150. data/lib/active_record/migration/command_recorder.rb +104 -9
  151. data/lib/active_record/migration/compatibility.rb +158 -64
  152. data/lib/active_record/migration/default_strategy.rb +23 -0
  153. data/lib/active_record/migration/execution_strategy.rb +19 -0
  154. data/lib/active_record/migration.rb +271 -117
  155. data/lib/active_record/model_schema.rb +82 -50
  156. data/lib/active_record/nested_attributes.rb +23 -3
  157. data/lib/active_record/normalization.rb +159 -0
  158. data/lib/active_record/persistence.rb +200 -47
  159. data/lib/active_record/promise.rb +84 -0
  160. data/lib/active_record/query_cache.rb +3 -21
  161. data/lib/active_record/query_logs.rb +87 -51
  162. data/lib/active_record/query_logs_formatter.rb +41 -0
  163. data/lib/active_record/querying.rb +16 -3
  164. data/lib/active_record/railtie.rb +127 -61
  165. data/lib/active_record/railties/controller_runtime.rb +12 -8
  166. data/lib/active_record/railties/databases.rake +142 -143
  167. data/lib/active_record/railties/job_runtime.rb +23 -0
  168. data/lib/active_record/readonly_attributes.rb +32 -5
  169. data/lib/active_record/reflection.rb +177 -45
  170. data/lib/active_record/relation/batches/batch_enumerator.rb +5 -3
  171. data/lib/active_record/relation/batches.rb +190 -61
  172. data/lib/active_record/relation/calculations.rb +200 -83
  173. data/lib/active_record/relation/delegation.rb +23 -9
  174. data/lib/active_record/relation/finder_methods.rb +77 -16
  175. data/lib/active_record/relation/merger.rb +2 -0
  176. data/lib/active_record/relation/predicate_builder/association_query_value.rb +31 -3
  177. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -6
  178. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  179. data/lib/active_record/relation/predicate_builder.rb +26 -14
  180. data/lib/active_record/relation/query_attribute.rb +25 -1
  181. data/lib/active_record/relation/query_methods.rb +429 -76
  182. data/lib/active_record/relation/spawn_methods.rb +18 -1
  183. data/lib/active_record/relation.rb +98 -41
  184. data/lib/active_record/result.rb +25 -9
  185. data/lib/active_record/runtime_registry.rb +10 -1
  186. data/lib/active_record/sanitization.rb +57 -16
  187. data/lib/active_record/schema.rb +36 -22
  188. data/lib/active_record/schema_dumper.rb +65 -23
  189. data/lib/active_record/schema_migration.rb +68 -33
  190. data/lib/active_record/scoping/default.rb +20 -12
  191. data/lib/active_record/scoping/named.rb +2 -2
  192. data/lib/active_record/scoping.rb +2 -1
  193. data/lib/active_record/secure_password.rb +60 -0
  194. data/lib/active_record/secure_token.rb +21 -3
  195. data/lib/active_record/serialization.rb +5 -0
  196. data/lib/active_record/signed_id.rb +9 -7
  197. data/lib/active_record/store.rb +16 -11
  198. data/lib/active_record/suppressor.rb +3 -1
  199. data/lib/active_record/table_metadata.rb +16 -3
  200. data/lib/active_record/tasks/database_tasks.rb +138 -107
  201. data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
  202. data/lib/active_record/tasks/postgresql_database_tasks.rb +17 -15
  203. data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
  204. data/lib/active_record/test_fixtures.rb +123 -99
  205. data/lib/active_record/timestamp.rb +26 -14
  206. data/lib/active_record/token_for.rb +113 -0
  207. data/lib/active_record/touch_later.rb +11 -6
  208. data/lib/active_record/transactions.rb +39 -13
  209. data/lib/active_record/translation.rb +1 -1
  210. data/lib/active_record/type/adapter_specific_registry.rb +1 -8
  211. data/lib/active_record/type/internal/timezone.rb +7 -2
  212. data/lib/active_record/type/serialized.rb +8 -4
  213. data/lib/active_record/type/time.rb +4 -0
  214. data/lib/active_record/validations/absence.rb +1 -1
  215. data/lib/active_record/validations/associated.rb +3 -3
  216. data/lib/active_record/validations/numericality.rb +5 -4
  217. data/lib/active_record/validations/presence.rb +5 -28
  218. data/lib/active_record/validations/uniqueness.rb +50 -5
  219. data/lib/active_record/validations.rb +8 -4
  220. data/lib/active_record/version.rb +1 -1
  221. data/lib/active_record.rb +143 -16
  222. data/lib/arel/errors.rb +10 -0
  223. data/lib/arel/factory_methods.rb +4 -0
  224. data/lib/arel/filter_predications.rb +1 -1
  225. data/lib/arel/nodes/and.rb +4 -0
  226. data/lib/arel/nodes/binary.rb +6 -1
  227. data/lib/arel/nodes/bound_sql_literal.rb +61 -0
  228. data/lib/arel/nodes/cte.rb +36 -0
  229. data/lib/arel/nodes/filter.rb +1 -1
  230. data/lib/arel/nodes/fragments.rb +35 -0
  231. data/lib/arel/nodes/homogeneous_in.rb +0 -8
  232. data/lib/arel/nodes/leading_join.rb +8 -0
  233. data/lib/arel/nodes/node.rb +111 -2
  234. data/lib/arel/nodes/sql_literal.rb +6 -0
  235. data/lib/arel/nodes/table_alias.rb +4 -0
  236. data/lib/arel/nodes.rb +4 -0
  237. data/lib/arel/predications.rb +2 -0
  238. data/lib/arel/table.rb +9 -5
  239. data/lib/arel/visitors/mysql.rb +8 -1
  240. data/lib/arel/visitors/to_sql.rb +81 -17
  241. data/lib/arel/visitors/visitor.rb +2 -2
  242. data/lib/arel.rb +16 -2
  243. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  244. data/lib/rails/generators/active_record/migration.rb +3 -1
  245. data/lib/rails/generators/active_record/model/USAGE +113 -0
  246. data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
  247. metadata +50 -15
  248. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
  249. data/lib/active_record/null_relation.rb +0 -63
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/module/attr_internal"
4
- require "active_record/log_subscriber"
4
+ require "active_record/runtime_registry"
5
5
 
6
6
  module ActiveRecord
7
7
  module Railties # :nodoc:
@@ -16,6 +16,11 @@ module ActiveRecord
16
16
  end
17
17
  end
18
18
 
19
+ def initialize(...) # :nodoc:
20
+ super
21
+ self.db_runtime = nil
22
+ end
23
+
19
24
  private
20
25
  attr_internal :db_runtime
21
26
 
@@ -23,16 +28,16 @@ module ActiveRecord
23
28
  # We also need to reset the runtime before each action
24
29
  # because of queries in middleware or in cases we are streaming
25
30
  # and it won't be cleaned up by the method below.
26
- ActiveRecord::LogSubscriber.reset_runtime
31
+ ActiveRecord::RuntimeRegistry.reset
27
32
  super
28
33
  end
29
34
 
30
35
  def cleanup_view_runtime
31
- if logger && logger.info? && ActiveRecord::Base.connected?
32
- db_rt_before_render = ActiveRecord::LogSubscriber.reset_runtime
36
+ if logger && logger.info?
37
+ db_rt_before_render = ActiveRecord::RuntimeRegistry.reset
33
38
  self.db_runtime = (db_runtime || 0) + db_rt_before_render
34
39
  runtime = super
35
- db_rt_after_render = ActiveRecord::LogSubscriber.reset_runtime
40
+ db_rt_after_render = ActiveRecord::RuntimeRegistry.reset
36
41
  self.db_runtime += db_rt_after_render
37
42
  runtime - db_rt_after_render
38
43
  else
@@ -42,9 +47,8 @@ module ActiveRecord
42
47
 
43
48
  def append_info_to_payload(payload)
44
49
  super
45
- if ActiveRecord::Base.connected?
46
- payload[:db_runtime] = (db_runtime || 0) + ActiveRecord::LogSubscriber.reset_runtime
47
- end
50
+
51
+ payload[:db_runtime] = (db_runtime || 0) + ActiveRecord::RuntimeRegistry.reset
48
52
  end
49
53
  end
50
54
  end
@@ -9,9 +9,10 @@ databases = ActiveRecord::Tasks::DatabaseTasks.setup_initial_database_yaml
9
9
  db_namespace = namespace :db do
10
10
  desc "Set the environment value for the database"
11
11
  task "environment:set" => :load_config do
12
- raise ActiveRecord::EnvironmentStorageError unless ActiveRecord::InternalMetadata.enabled?
13
- ActiveRecord::InternalMetadata.create_table
14
- ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Base.connection.migration_context.current_environment
12
+ connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection
13
+ raise ActiveRecord::EnvironmentStorageError unless connection.internal_metadata.enabled?
14
+
15
+ connection.internal_metadata.create_table_and_set_flags(connection.migration_context.current_environment)
15
16
  end
16
17
 
17
18
  task check_protected_environments: :load_config do
@@ -40,7 +41,7 @@ db_namespace = namespace :db do
40
41
  end
41
42
  end
42
43
 
43
- 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, except when DATABASE_URL is present."
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."
44
45
  task create: [:load_config] do
45
46
  ActiveRecord::Tasks::DatabaseTasks.create_current
46
47
  end
@@ -59,7 +60,7 @@ db_namespace = namespace :db do
59
60
  end
60
61
  end
61
62
 
62
- 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, except when DATABASE_URL is present."
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."
63
64
  task drop: [:load_config, :check_protected_environments] do
64
65
  db_namespace["drop:_unsafe"].invoke
65
66
  end
@@ -91,20 +92,18 @@ db_namespace = namespace :db do
91
92
  if db_configs.size == 1
92
93
  ActiveRecord::Tasks::DatabaseTasks.migrate
93
94
  else
94
- original_db_config = ActiveRecord::Base.connection_db_config
95
95
  mapped_versions = ActiveRecord::Tasks::DatabaseTasks.db_configs_with_versions(db_configs)
96
96
 
97
97
  mapped_versions.sort.each do |version, db_configs|
98
98
  db_configs.each do |db_config|
99
- ActiveRecord::Base.establish_connection(db_config)
100
- ActiveRecord::Tasks::DatabaseTasks.migrate(version)
99
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection(db_config) do
100
+ ActiveRecord::Tasks::DatabaseTasks.migrate(version)
101
+ end
101
102
  end
102
103
  end
103
104
  end
104
105
 
105
106
  db_namespace["_dump"].invoke
106
- ensure
107
- ActiveRecord::Base.establish_connection(original_db_config) if original_db_config
108
107
  end
109
108
 
110
109
  # IMPORTANT: This task won't dump the schema if ActiveRecord.dump_schema_after_migration is set to false
@@ -121,10 +120,7 @@ db_namespace = namespace :db do
121
120
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
122
121
  # IMPORTANT: This task won't dump the schema if ActiveRecord.dump_schema_after_migration is set to false
123
122
  task name do
124
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, name: name)
125
-
126
- if ActiveRecord.dump_schema_after_migration && db_config.schema_dump
127
- ActiveRecord::Base.establish_connection(db_config)
123
+ if ActiveRecord.dump_schema_after_migration
128
124
  db_namespace["schema:dump:#{name}"].invoke
129
125
  end
130
126
 
@@ -139,17 +135,15 @@ db_namespace = namespace :db do
139
135
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
140
136
  desc "Migrate #{name} database for current environment"
141
137
  task name => :load_config do
142
- original_db_config = ActiveRecord::Base.connection_db_config
143
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: name)
144
- ActiveRecord::Base.establish_connection(db_config)
145
- ActiveRecord::Tasks::DatabaseTasks.migrate
138
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: Rails.env, name: name) do |conn|
139
+ ActiveRecord::Tasks::DatabaseTasks.migrate
140
+ end
141
+
146
142
  db_namespace["_dump:#{name}"].invoke
147
- ensure
148
- ActiveRecord::Base.establish_connection(original_db_config)
149
143
  end
150
144
  end
151
145
 
152
- desc "Rolls back the database one migration and re-migrates up (options: STEP=x, VERSION=x)."
146
+ desc "Roll back the database one migration and re-migrate up (options: STEP=x, VERSION=x)."
153
147
  task redo: :load_config do
154
148
  ActiveRecord::Tasks::DatabaseTasks.raise_for_multi_db(command: "db:migrate:redo")
155
149
 
@@ -166,7 +160,7 @@ db_namespace = namespace :db do
166
160
 
167
161
  namespace :redo do
168
162
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
169
- desc "Rolls back #{name} database one migration and re-migrates up (options: STEP=x, VERSION=x)."
163
+ desc "Roll back #{name} database one migration and re-migrate up (options: STEP=x, VERSION=x)."
170
164
  task name => :load_config do
171
165
  raise "Empty VERSION provided" if ENV["VERSION"] && ENV["VERSION"].empty?
172
166
 
@@ -184,7 +178,7 @@ db_namespace = namespace :db do
184
178
  # desc 'Resets your database using your migrations for the current environment'
185
179
  task reset: ["db:drop", "db:create", "db:migrate"]
186
180
 
187
- desc 'Runs the "up" for a given migration VERSION.'
181
+ desc 'Run the "up" for a given migration VERSION.'
188
182
  task up: :load_config do
189
183
  ActiveRecord::Tasks::DatabaseTasks.raise_for_multi_db(command: "db:migrate:up")
190
184
 
@@ -192,7 +186,7 @@ db_namespace = namespace :db do
192
186
 
193
187
  ActiveRecord::Tasks::DatabaseTasks.check_target_version
194
188
 
195
- ActiveRecord::Base.connection.migration_context.run(
189
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection.migration_context.run(
196
190
  :up,
197
191
  ActiveRecord::Tasks::DatabaseTasks.target_version
198
192
  )
@@ -201,24 +195,21 @@ db_namespace = namespace :db do
201
195
 
202
196
  namespace :up do
203
197
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
198
+ desc 'Run the "up" on #{name} database for a given migration VERSION.'
204
199
  task name => :load_config do
205
200
  raise "VERSION is required" if !ENV["VERSION"] || ENV["VERSION"].empty?
206
201
 
207
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: name)
208
-
209
- ActiveRecord::Base.establish_connection(db_config)
210
- ActiveRecord::Tasks::DatabaseTasks.check_target_version
211
- ActiveRecord::Base.connection.migration_context.run(
212
- :up,
213
- ActiveRecord::Tasks::DatabaseTasks.target_version
214
- )
202
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: Rails.env, name: name) do |conn|
203
+ ActiveRecord::Tasks::DatabaseTasks.check_target_version
204
+ conn.migration_context.run(:up, ActiveRecord::Tasks::DatabaseTasks.target_version)
205
+ end
215
206
 
216
207
  db_namespace["_dump"].invoke
217
208
  end
218
209
  end
219
210
  end
220
211
 
221
- desc 'Runs the "down" for a given migration VERSION.'
212
+ desc 'Run the "down" for a given migration VERSION.'
222
213
  task down: :load_config do
223
214
  ActiveRecord::Tasks::DatabaseTasks.raise_for_multi_db(command: "db:migrate:down")
224
215
 
@@ -226,7 +217,7 @@ db_namespace = namespace :db do
226
217
 
227
218
  ActiveRecord::Tasks::DatabaseTasks.check_target_version
228
219
 
229
- ActiveRecord::Base.connection.migration_context.run(
220
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection.migration_context.run(
230
221
  :down,
231
222
  ActiveRecord::Tasks::DatabaseTasks.target_version
232
223
  )
@@ -235,17 +226,14 @@ db_namespace = namespace :db do
235
226
 
236
227
  namespace :down do
237
228
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
229
+ desc 'Run the "down" on #{name} database for a given migration VERSION.'
238
230
  task name => :load_config do
239
231
  raise "VERSION is required" if !ENV["VERSION"] || ENV["VERSION"].empty?
240
232
 
241
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: name)
242
-
243
- ActiveRecord::Base.establish_connection(db_config)
244
- ActiveRecord::Tasks::DatabaseTasks.check_target_version
245
- ActiveRecord::Base.connection.migration_context.run(
246
- :down,
247
- ActiveRecord::Tasks::DatabaseTasks.target_version
248
- )
233
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: Rails.env, name: name) do |conn|
234
+ ActiveRecord::Tasks::DatabaseTasks.check_target_version
235
+ conn.migration_context.run(:down, ActiveRecord::Tasks::DatabaseTasks.target_version)
236
+ end
249
237
 
250
238
  db_namespace["_dump"].invoke
251
239
  end
@@ -254,8 +242,7 @@ db_namespace = namespace :db do
254
242
 
255
243
  desc "Display status of migrations"
256
244
  task status: :load_config do
257
- ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
258
- ActiveRecord::Base.establish_connection(db_config)
245
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each do
259
246
  ActiveRecord::Tasks::DatabaseTasks.migrate_status
260
247
  end
261
248
  end
@@ -264,9 +251,9 @@ db_namespace = namespace :db do
264
251
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
265
252
  desc "Display status of migrations for #{name} database"
266
253
  task name => :load_config do
267
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: name)
268
- ActiveRecord::Base.establish_connection(db_config)
269
- ActiveRecord::Tasks::DatabaseTasks.migrate_status
254
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: Rails.env, name: name) do
255
+ ActiveRecord::Tasks::DatabaseTasks.migrate_status
256
+ end
270
257
  end
271
258
  end
272
259
  end
@@ -277,24 +264,24 @@ db_namespace = namespace :db do
277
264
  desc "Rollback #{name} database for current environment (specify steps w/ STEP=n)."
278
265
  task name => :load_config do
279
266
  step = ENV["STEP"] ? ENV["STEP"].to_i : 1
280
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: name)
281
267
 
282
- ActiveRecord::Base.establish_connection(db_config)
283
- ActiveRecord::Base.connection.migration_context.rollback(step)
268
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: Rails.env, name: name) do |conn|
269
+ conn.migration_context.rollback(step)
270
+ end
284
271
 
285
272
  db_namespace["_dump"].invoke
286
273
  end
287
274
  end
288
275
  end
289
276
 
290
- desc "Rolls the schema back to the previous version (specify steps w/ STEP=n)."
277
+ desc "Roll the schema back to the previous version (specify steps w/ STEP=n)."
291
278
  task rollback: :load_config do
292
279
  ActiveRecord::Tasks::DatabaseTasks.raise_for_multi_db(command: "db:rollback")
293
280
  raise "VERSION is not supported - To rollback a specific version, use db:migrate:down" if ENV["VERSION"]
294
281
 
295
282
  step = ENV["STEP"] ? ENV["STEP"].to_i : 1
296
283
 
297
- ActiveRecord::Base.connection.migration_context.rollback(step)
284
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection.migration_context.rollback(step)
298
285
 
299
286
  db_namespace["_dump"].invoke
300
287
  end
@@ -302,7 +289,9 @@ db_namespace = namespace :db do
302
289
  # desc 'Pushes the schema to the next version (specify steps w/ STEP=n).'
303
290
  task forward: :load_config do
304
291
  step = ENV["STEP"] ? ENV["STEP"].to_i : 1
305
- ActiveRecord::Base.connection.migration_context.forward(step)
292
+
293
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection.migration_context.forward(step)
294
+
306
295
  db_namespace["_dump"].invoke
307
296
  end
308
297
 
@@ -310,65 +299,84 @@ db_namespace = namespace :db do
310
299
  task all: ["db:drop", "db:setup"]
311
300
 
312
301
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
313
- desc "Drops and recreates the #{name} database from its schema for the current environment and loads the seeds."
302
+ desc "Drop and recreate the #{name} database from its schema for the current environment and load the seeds."
314
303
  task name => ["db:drop:#{name}", "db:setup:#{name}"]
315
304
  end
316
305
  end
317
306
 
318
- desc "Drops and recreates all databases from their schema for the current environment and loads the seeds."
307
+ desc "Drop and recreate all databases from their schema for the current environment and load the seeds."
319
308
  task reset: [ "db:drop", "db:setup" ]
320
309
 
321
- # desc "Retrieves the charset for the current environment's database"
310
+ # desc "Retrieve the charset for the current environment's database"
322
311
  task charset: :load_config do
323
312
  puts ActiveRecord::Tasks::DatabaseTasks.charset_current
324
313
  end
325
314
 
326
- # desc "Retrieves the collation for the current environment's database"
315
+ # desc "Retrieve the collation for the current environment's database"
327
316
  task collation: :load_config do
328
317
  puts ActiveRecord::Tasks::DatabaseTasks.collation_current
329
318
  rescue NoMethodError
330
319
  $stderr.puts "Sorry, your database adapter is not supported yet. Feel free to submit a patch."
331
320
  end
332
321
 
333
- desc "Retrieves the current schema version number"
322
+ desc "Retrieve the current schema version number"
334
323
  task version: :load_config do
335
- puts "Current version: #{ActiveRecord::Base.connection.schema_version}"
324
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: Rails.env) do |connection|
325
+ puts "\ndatabase: #{connection.pool.db_config.database}\n"
326
+ puts "Current version: #{connection.schema_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
336
341
  end
337
342
 
338
343
  # desc "Raises an error if there are pending migrations"
339
344
  task abort_if_pending_migrations: :load_config do
340
- pending_migrations = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).flat_map do |db_config|
341
- ActiveRecord::Base.establish_connection(db_config)
345
+ pending_migrations = []
342
346
 
343
- ActiveRecord::Base.connection.migration_context.open.pending_migrations
347
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each do |conn|
348
+ pending_migrations << conn.migration_context.open.pending_migrations
344
349
  end
345
350
 
351
+ pending_migrations = pending_migrations.flatten!
352
+
346
353
  if pending_migrations.any?
347
354
  puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}"
355
+
348
356
  pending_migrations.each do |pending_migration|
349
357
  puts " %4d %s" % [pending_migration.version, pending_migration.name]
350
358
  end
359
+
351
360
  abort %{Run `bin/rails db:migrate` to update your database then try again.}
352
361
  end
353
- ensure
354
- ActiveRecord::Base.establish_connection(ActiveRecord::Tasks::DatabaseTasks.env.to_sym)
355
362
  end
356
363
 
357
364
  namespace :abort_if_pending_migrations do
358
365
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
359
- # desc "Raises an error if there are pending migrations for #{name} database"
366
+ # desc "Raise an error if there are pending migrations for #{name} database"
360
367
  task name => :load_config do
361
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, name: name)
362
- ActiveRecord::Base.establish_connection(db_config)
368
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: Rails.env, name: name) do |conn|
369
+ pending_migrations = conn.migration_context.open.pending_migrations
363
370
 
364
- pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations
371
+ if pending_migrations.any?
372
+ puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}"
365
373
 
366
- if pending_migrations.any?
367
- puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}"
368
- pending_migrations.each do |pending_migration|
369
- puts " %4d %s" % [pending_migration.version, pending_migration.name]
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.}
370
379
  end
371
- abort %{Run `bin/rails db:migrate:#{name}` to update your database then try again.}
372
380
  end
373
381
  end
374
382
  end
@@ -378,32 +386,32 @@ db_namespace = namespace :db do
378
386
  task all: ["db:create", :environment, "db:schema:load", :seed]
379
387
 
380
388
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
381
- desc "Creates the #{name} database, loads the schema, and initializes with the seed data (use db:reset:#{name} to also drop the database first)"
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)"
382
390
  task name => ["db:create:#{name}", :environment, "db:schema:load:#{name}", "db:seed"]
383
391
  end
384
392
  end
385
393
 
386
- desc "Creates all databases, loads all schemas, and initializes with the seed data (use db:reset to also drop all databases first)"
394
+ desc "Create all databases, load all schemas, and initialize with the seed data (use db:reset to also drop all databases first)"
387
395
  task setup: ["db:create", :environment, "db:schema:load", :seed]
388
396
 
389
- desc "Runs setup if database does not exist, or runs migrations if it does"
397
+ desc "Run setup if database does not exist, or run migrations if it does"
390
398
  task prepare: :load_config do
391
399
  ActiveRecord::Tasks::DatabaseTasks.prepare_all
392
400
  end
393
401
 
394
- desc "Loads the seed data from db/seeds.rb"
402
+ desc "Load the seed data from db/seeds.rb"
395
403
  task seed: :load_config do
396
404
  db_namespace["abort_if_pending_migrations"].invoke
397
405
  ActiveRecord::Tasks::DatabaseTasks.load_seed
398
406
  end
399
407
 
400
408
  namespace :seed do
401
- 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"
402
410
  task replant: [:load_config, :truncate_all, :seed]
403
411
  end
404
412
 
405
413
  namespace :fixtures do
406
- 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 (e.g. 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."
407
415
  task load: :load_config do
408
416
  require "active_record/fixtures"
409
417
 
@@ -452,30 +460,32 @@ db_namespace = namespace :db do
452
460
  end
453
461
 
454
462
  namespace :schema do
455
- desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`)"
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`)"
456
464
  task dump: :load_config do
457
- ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
458
- if db_config.schema_dump
459
- ActiveRecord::Base.establish_connection(db_config)
460
- ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config)
461
- end
465
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each do |conn|
466
+ db_config = conn.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)
462
469
  end
463
470
 
464
471
  db_namespace["schema:dump"].reenable
465
472
  end
466
473
 
467
- desc "Loads a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) 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"
468
475
  task load: [:load_config, :check_protected_environments] do
469
476
  ActiveRecord::Tasks::DatabaseTasks.load_schema_current(ActiveRecord.schema_format, ENV["SCHEMA"])
470
477
  end
471
478
 
472
479
  namespace :dump do
473
480
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
474
- desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) for #{name} database"
481
+ 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"
475
482
  task name => :load_config do
476
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, name: name)
477
- ActiveRecord::Base.establish_connection(db_config)
478
- ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config)
483
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(name: name) do |conn|
484
+ db_config = conn.pool.db_config
485
+ schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
486
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, schema_format)
487
+ end
488
+
479
489
  db_namespace["schema:dump:#{name}"].reenable
480
490
  end
481
491
  end
@@ -483,34 +493,29 @@ db_namespace = namespace :db do
483
493
 
484
494
  namespace :load do
485
495
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
486
- desc "Loads a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) into the #{name} database"
487
- task name => :load_config do
488
- original_db_config = ActiveRecord::Base.connection_db_config
489
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, name: name)
490
- ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config)
491
- ensure
492
- ActiveRecord::Base.establish_connection(original_db_config) if original_db_config
496
+ 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"
497
+ task name => "db:test:purge:#{name}" do
498
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(name: name) do |conn|
499
+ db_config = conn.pool.db_config
500
+ schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
501
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
502
+ end
493
503
  end
494
504
  end
495
505
  end
496
506
 
497
507
  namespace :cache do
498
- desc "Creates a db/schema_cache.yml file."
508
+ desc "Create a db/schema_cache.yml file."
499
509
  task dump: :load_config do
500
- ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
501
- ActiveRecord::Base.establish_connection(db_config)
502
- filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(
503
- db_config.name,
504
- schema_cache_path: db_config.schema_cache_path,
505
- )
506
- ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(
507
- ActiveRecord::Base.connection,
508
- filename,
509
- )
510
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each do |conn|
511
+ db_config = conn.pool.db_config
512
+ filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(db_config.name, schema_cache_path: db_config.schema_cache_path)
513
+
514
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(conn, filename)
510
515
  end
511
516
  end
512
517
 
513
- desc "Clears a db/schema_cache.yml file."
518
+ desc "Clear a db/schema_cache.yml file."
514
519
  task clear: :load_config do
515
520
  ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
516
521
  filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(
@@ -540,21 +545,13 @@ db_namespace = namespace :db do
540
545
  end
541
546
 
542
547
  namespace :test do
543
- # desc "Recreate the test database from the current schema"
544
- task load: %w(db:test:purge) do
545
- db_namespace["test:load_schema"].invoke
546
- end
547
-
548
- # desc "Recreate the test database from an existent schema file (schema.rb or structure.sql, depending on `config.active_record.schema_format`)"
548
+ # 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`)"
549
549
  task load_schema: %w(db:test:purge) do
550
- should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
551
- ActiveRecord::Schema.verbose = false
552
- ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
553
- ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config)
554
- end
555
- ensure
556
- if should_reconnect
557
- ActiveRecord::Base.establish_connection(ActiveRecord::Tasks::DatabaseTasks.env.to_sym)
550
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: "test") do |conn|
551
+ db_config = conn.pool.db_config
552
+ ActiveRecord::Schema.verbose = false
553
+ schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
554
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
558
555
  end
559
556
  end
560
557
 
@@ -568,28 +565,19 @@ db_namespace = namespace :db do
568
565
  # desc 'Load the test schema'
569
566
  task prepare: :load_config do
570
567
  unless ActiveRecord::Base.configurations.blank?
571
- db_namespace["test:load"].invoke
568
+ db_namespace["test:load_schema"].invoke
572
569
  end
573
570
  end
574
571
 
575
572
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
576
- # desc "Recreate the #{name} test database"
577
- namespace :load do
578
- task name => "db:test:purge:#{name}" do
579
- db_namespace["test:load_schema:#{name}"].invoke
580
- end
581
- end
582
-
583
573
  # desc "Recreate the #{name} test database from an existent schema.rb file"
584
574
  namespace :load_schema do
585
575
  task name => "db:test:purge:#{name}" do
586
- should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
587
- ActiveRecord::Schema.verbose = false
588
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: "test", name: name)
589
- ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config)
590
- ensure
591
- if should_reconnect
592
- ActiveRecord::Base.establish_connection(ActiveRecord::Tasks::DatabaseTasks.env.to_sym)
576
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: "test", name: name) do |conn|
577
+ db_config = conn.pool.db_config
578
+ ActiveRecord::Schema.verbose = false
579
+ schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
580
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
593
581
  end
594
582
  end
595
583
  end
@@ -597,15 +585,17 @@ db_namespace = namespace :db do
597
585
  # desc "Empty the #{name} test database"
598
586
  namespace :purge do
599
587
  task name => %w(load_config check_protected_environments) do
600
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: "test", name: name)
601
- ActiveRecord::Tasks::DatabaseTasks.purge(db_config)
588
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: "test", name: name) do |conn|
589
+ db_config = conn.pool.db_config
590
+ ActiveRecord::Tasks::DatabaseTasks.purge(db_config)
591
+ end
602
592
  end
603
593
  end
604
594
 
605
595
  # desc 'Load the #{name} database test schema'
606
596
  namespace :prepare do
607
597
  task name => :load_config do
608
- db_namespace["test:load:#{name}"].invoke
598
+ db_namespace["test:load_schema:#{name}"].invoke
609
599
  end
610
600
  end
611
601
  end
@@ -614,7 +604,7 @@ end
614
604
 
615
605
  namespace :railties do
616
606
  namespace :install do
617
- # desc "Copies missing migrations from Railties (e.g. engines). You can specify Railties to use with FROM=railtie1,railtie2"
607
+ # 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."
618
608
  task migrations: :'db:load_config' do
619
609
  to_load = ENV["FROM"].blank? ? :all : ENV["FROM"].split(",").map(&:strip)
620
610
  railties = {}
@@ -638,7 +628,16 @@ namespace :railties do
638
628
  puts "Copied migration #{migration.basename} from #{name}"
639
629
  end
640
630
 
641
- ActiveRecord::Migration.copy(ActiveRecord::Tasks::DatabaseTasks.migrations_paths.first, railties,
631
+ if ENV["DATABASE"].present? && ENV["DATABASE"] != "primary"
632
+ config = ActiveRecord::Base.configurations.configs_for(name: ENV["DATABASE"])
633
+ raise "Invalid DATABASE provided" if config.blank?
634
+ destination = config.migrations_paths
635
+ raise "#{ENV["DATABASE"]} does not have a custom migration path" if destination.blank?
636
+ else
637
+ destination = ActiveRecord::Tasks::DatabaseTasks.migrations_paths.first
638
+ end
639
+
640
+ ActiveRecord::Migration.copy(destination, railties,
642
641
  on_skip: on_skip, on_copy: on_copy)
643
642
  end
644
643
  end