activerecord 7.0.0 → 7.1.2

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 (251) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1701 -1039
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +18 -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 +362 -236
  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 +52 -34
  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 +129 -31
  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 -131
  56. data/lib/active_record/connection_adapters/abstract/transaction.rb +287 -58
  57. data/lib/active_record/connection_adapters/abstract_adapter.rb +513 -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 +151 -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 +16 -3
  72. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +75 -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/money.rb +3 -2
  76. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
  77. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +4 -2
  78. data/lib/active_record/connection_adapters/postgresql/quoting.rb +41 -8
  79. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +6 -10
  80. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
  81. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +131 -2
  82. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +53 -0
  83. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +372 -63
  84. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
  85. data/lib/active_record/connection_adapters/postgresql_adapter.rb +359 -197
  86. data/lib/active_record/connection_adapters/schema_cache.rb +287 -59
  87. data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
  88. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +52 -39
  89. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +22 -5
  90. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
  91. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +41 -22
  92. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +242 -81
  93. data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
  94. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
  95. data/lib/active_record/connection_adapters/trilogy_adapter.rb +254 -0
  96. data/lib/active_record/connection_adapters.rb +3 -1
  97. data/lib/active_record/connection_handling.rb +73 -96
  98. data/lib/active_record/core.rb +142 -153
  99. data/lib/active_record/counter_cache.rb +46 -25
  100. data/lib/active_record/database_configurations/connection_url_resolver.rb +1 -0
  101. data/lib/active_record/database_configurations/database_config.rb +9 -3
  102. data/lib/active_record/database_configurations/hash_config.rb +22 -12
  103. data/lib/active_record/database_configurations/url_config.rb +17 -11
  104. data/lib/active_record/database_configurations.rb +87 -34
  105. data/lib/active_record/delegated_type.rb +9 -4
  106. data/lib/active_record/deprecator.rb +7 -0
  107. data/lib/active_record/destroy_association_async_job.rb +2 -0
  108. data/lib/active_record/disable_joins_association_relation.rb +1 -1
  109. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  110. data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
  111. data/lib/active_record/encryption/config.rb +25 -1
  112. data/lib/active_record/encryption/configurable.rb +13 -14
  113. data/lib/active_record/encryption/context.rb +10 -3
  114. data/lib/active_record/encryption/contexts.rb +8 -4
  115. data/lib/active_record/encryption/derived_secret_key_provider.rb +9 -3
  116. data/lib/active_record/encryption/deterministic_key_provider.rb +1 -1
  117. data/lib/active_record/encryption/encryptable_record.rb +38 -22
  118. data/lib/active_record/encryption/encrypted_attribute_type.rb +19 -8
  119. data/lib/active_record/encryption/encryptor.rb +7 -7
  120. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +3 -3
  121. data/lib/active_record/encryption/extended_deterministic_queries.rb +83 -86
  122. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +3 -3
  123. data/lib/active_record/encryption/key_generator.rb +12 -1
  124. data/lib/active_record/encryption/message.rb +1 -1
  125. data/lib/active_record/encryption/message_serializer.rb +2 -0
  126. data/lib/active_record/encryption/properties.rb +4 -4
  127. data/lib/active_record/encryption/scheme.rb +20 -23
  128. data/lib/active_record/encryption.rb +1 -0
  129. data/lib/active_record/enum.rb +113 -29
  130. data/lib/active_record/errors.rb +108 -15
  131. data/lib/active_record/explain.rb +23 -3
  132. data/lib/active_record/explain_subscriber.rb +1 -1
  133. data/lib/active_record/fixture_set/model_metadata.rb +14 -4
  134. data/lib/active_record/fixture_set/render_context.rb +2 -0
  135. data/lib/active_record/fixture_set/table_row.rb +29 -8
  136. data/lib/active_record/fixtures.rb +121 -73
  137. data/lib/active_record/future_result.rb +30 -5
  138. data/lib/active_record/gem_version.rb +3 -3
  139. data/lib/active_record/inheritance.rb +30 -16
  140. data/lib/active_record/insert_all.rb +57 -10
  141. data/lib/active_record/integration.rb +10 -10
  142. data/lib/active_record/internal_metadata.rb +120 -30
  143. data/lib/active_record/locking/optimistic.rb +32 -18
  144. data/lib/active_record/locking/pessimistic.rb +8 -5
  145. data/lib/active_record/log_subscriber.rb +39 -17
  146. data/lib/active_record/marshalling.rb +56 -0
  147. data/lib/active_record/message_pack.rb +124 -0
  148. data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
  149. data/lib/active_record/middleware/database_selector.rb +18 -13
  150. data/lib/active_record/middleware/shard_selector.rb +7 -5
  151. data/lib/active_record/migration/command_recorder.rb +108 -10
  152. data/lib/active_record/migration/compatibility.rb +158 -64
  153. data/lib/active_record/migration/default_strategy.rb +23 -0
  154. data/lib/active_record/migration/execution_strategy.rb +19 -0
  155. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  156. data/lib/active_record/migration.rb +274 -117
  157. data/lib/active_record/model_schema.rb +86 -54
  158. data/lib/active_record/nested_attributes.rb +24 -6
  159. data/lib/active_record/normalization.rb +167 -0
  160. data/lib/active_record/persistence.rb +200 -47
  161. data/lib/active_record/promise.rb +84 -0
  162. data/lib/active_record/query_cache.rb +3 -21
  163. data/lib/active_record/query_logs.rb +87 -51
  164. data/lib/active_record/query_logs_formatter.rb +41 -0
  165. data/lib/active_record/querying.rb +16 -3
  166. data/lib/active_record/railtie.rb +128 -62
  167. data/lib/active_record/railties/controller_runtime.rb +12 -8
  168. data/lib/active_record/railties/databases.rake +145 -146
  169. data/lib/active_record/railties/job_runtime.rb +23 -0
  170. data/lib/active_record/readonly_attributes.rb +32 -5
  171. data/lib/active_record/reflection.rb +189 -45
  172. data/lib/active_record/relation/batches/batch_enumerator.rb +5 -3
  173. data/lib/active_record/relation/batches.rb +190 -61
  174. data/lib/active_record/relation/calculations.rb +208 -83
  175. data/lib/active_record/relation/delegation.rb +23 -9
  176. data/lib/active_record/relation/finder_methods.rb +77 -16
  177. data/lib/active_record/relation/merger.rb +2 -0
  178. data/lib/active_record/relation/predicate_builder/association_query_value.rb +31 -3
  179. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -6
  180. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  181. data/lib/active_record/relation/predicate_builder.rb +26 -14
  182. data/lib/active_record/relation/query_attribute.rb +25 -1
  183. data/lib/active_record/relation/query_methods.rb +430 -77
  184. data/lib/active_record/relation/spawn_methods.rb +18 -1
  185. data/lib/active_record/relation.rb +98 -41
  186. data/lib/active_record/result.rb +25 -9
  187. data/lib/active_record/runtime_registry.rb +10 -1
  188. data/lib/active_record/sanitization.rb +57 -16
  189. data/lib/active_record/schema.rb +36 -22
  190. data/lib/active_record/schema_dumper.rb +65 -23
  191. data/lib/active_record/schema_migration.rb +68 -33
  192. data/lib/active_record/scoping/default.rb +20 -12
  193. data/lib/active_record/scoping/named.rb +2 -2
  194. data/lib/active_record/scoping.rb +2 -1
  195. data/lib/active_record/secure_password.rb +60 -0
  196. data/lib/active_record/secure_token.rb +21 -3
  197. data/lib/active_record/serialization.rb +5 -0
  198. data/lib/active_record/signed_id.rb +9 -7
  199. data/lib/active_record/store.rb +16 -11
  200. data/lib/active_record/suppressor.rb +3 -1
  201. data/lib/active_record/table_metadata.rb +16 -3
  202. data/lib/active_record/tasks/database_tasks.rb +138 -107
  203. data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
  204. data/lib/active_record/tasks/postgresql_database_tasks.rb +17 -15
  205. data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
  206. data/lib/active_record/test_fixtures.rb +123 -99
  207. data/lib/active_record/timestamp.rb +27 -15
  208. data/lib/active_record/token_for.rb +113 -0
  209. data/lib/active_record/touch_later.rb +11 -6
  210. data/lib/active_record/transactions.rb +39 -13
  211. data/lib/active_record/translation.rb +1 -1
  212. data/lib/active_record/type/adapter_specific_registry.rb +1 -8
  213. data/lib/active_record/type/internal/timezone.rb +7 -2
  214. data/lib/active_record/type/serialized.rb +8 -4
  215. data/lib/active_record/type/time.rb +4 -0
  216. data/lib/active_record/validations/absence.rb +1 -1
  217. data/lib/active_record/validations/associated.rb +3 -3
  218. data/lib/active_record/validations/numericality.rb +5 -4
  219. data/lib/active_record/validations/presence.rb +5 -28
  220. data/lib/active_record/validations/uniqueness.rb +50 -5
  221. data/lib/active_record/validations.rb +8 -4
  222. data/lib/active_record/version.rb +1 -1
  223. data/lib/active_record.rb +143 -16
  224. data/lib/arel/errors.rb +10 -0
  225. data/lib/arel/factory_methods.rb +4 -0
  226. data/lib/arel/filter_predications.rb +1 -1
  227. data/lib/arel/nodes/and.rb +4 -0
  228. data/lib/arel/nodes/binary.rb +6 -1
  229. data/lib/arel/nodes/bound_sql_literal.rb +61 -0
  230. data/lib/arel/nodes/cte.rb +36 -0
  231. data/lib/arel/nodes/filter.rb +1 -1
  232. data/lib/arel/nodes/fragments.rb +35 -0
  233. data/lib/arel/nodes/homogeneous_in.rb +1 -9
  234. data/lib/arel/nodes/leading_join.rb +8 -0
  235. data/lib/arel/nodes/node.rb +111 -2
  236. data/lib/arel/nodes/sql_literal.rb +6 -0
  237. data/lib/arel/nodes/table_alias.rb +4 -0
  238. data/lib/arel/nodes.rb +4 -0
  239. data/lib/arel/predications.rb +2 -0
  240. data/lib/arel/table.rb +9 -5
  241. data/lib/arel/visitors/mysql.rb +8 -1
  242. data/lib/arel/visitors/to_sql.rb +81 -17
  243. data/lib/arel/visitors/visitor.rb +2 -2
  244. data/lib/arel.rb +16 -2
  245. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  246. data/lib/rails/generators/active_record/migration.rb +3 -1
  247. data/lib/rails/generators/active_record/model/USAGE +113 -0
  248. data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
  249. metadata +51 -15
  250. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
  251. data/lib/active_record/null_relation.rb +0 -63
@@ -7,6 +7,7 @@ require "active_support/core_ext/array/access"
7
7
  require "active_support/core_ext/enumerable"
8
8
  require "active_support/core_ext/module/attribute_accessors"
9
9
  require "active_support/actionable_error"
10
+ require "active_record/migration/pending_migration_connection"
10
11
 
11
12
  module ActiveRecord
12
13
  class MigrationError < ActiveRecordError # :nodoc:
@@ -20,7 +21,7 @@ module ActiveRecord
20
21
  # For example the following migration is not reversible.
21
22
  # Rolling back this migration will raise an ActiveRecord::IrreversibleMigration error.
22
23
  #
23
- # class IrreversibleMigrationExample < ActiveRecord::Migration[7.0]
24
+ # class IrreversibleMigrationExample < ActiveRecord::Migration[7.1]
24
25
  # def change
25
26
  # create_table :distributors do |t|
26
27
  # t.string :zipcode
@@ -38,7 +39,7 @@ module ActiveRecord
38
39
  #
39
40
  # 1. Define <tt>#up</tt> and <tt>#down</tt> methods instead of <tt>#change</tt>:
40
41
  #
41
- # class ReversibleMigrationExample < ActiveRecord::Migration[7.0]
42
+ # class ReversibleMigrationExample < ActiveRecord::Migration[7.1]
42
43
  # def up
43
44
  # create_table :distributors do |t|
44
45
  # t.string :zipcode
@@ -63,7 +64,7 @@ module ActiveRecord
63
64
  #
64
65
  # 2. Use the #reversible method in <tt>#change</tt> method:
65
66
  #
66
- # class ReversibleMigrationExample < ActiveRecord::Migration[7.0]
67
+ # class ReversibleMigrationExample < ActiveRecord::Migration[7.1]
67
68
  # def change
68
69
  # create_table :distributors do |t|
69
70
  # t.string :zipcode
@@ -137,32 +138,38 @@ module ActiveRecord
137
138
  ActiveRecord::Tasks::DatabaseTasks.migrate
138
139
 
139
140
  if ActiveRecord.dump_schema_after_migration
140
- ActiveRecord::Tasks::DatabaseTasks.dump_schema(
141
- ActiveRecord::Base.connection_db_config
142
- )
141
+ connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection
142
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema(connection.pool.db_config)
143
143
  end
144
144
  end
145
145
 
146
- def initialize(message = nil)
147
- super(message || detailed_migration_message)
146
+ def initialize(message = nil, pending_migrations: nil)
147
+ if pending_migrations.nil?
148
+ connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection
149
+ pending_migrations = connection.migration_context.open.pending_migrations
150
+ end
151
+
152
+ super(message || detailed_migration_message(pending_migrations))
148
153
  end
149
154
 
150
155
  private
151
- def detailed_migration_message
156
+ def detailed_migration_message(pending_migrations)
152
157
  message = "Migrations are pending. To resolve this issue, run:\n\n bin/rails db:migrate"
153
- message += " RAILS_ENV=#{::Rails.env}" if defined?(Rails.env)
158
+ message += " RAILS_ENV=#{::Rails.env}" if defined?(Rails.env) && !Rails.env.local?
154
159
  message += "\n\n"
155
160
 
156
- pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations
157
-
158
161
  message += "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}\n\n"
159
162
 
160
163
  pending_migrations.each do |pending_migration|
161
- message += "#{pending_migration.basename}\n"
164
+ message += "#{pending_migration.filename}\n"
162
165
  end
163
166
 
164
167
  message
165
168
  end
169
+
170
+ def connection
171
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection
172
+ end
166
173
  end
167
174
 
168
175
  class ConcurrentMigrationError < MigrationError # :nodoc:
@@ -228,7 +235,7 @@ module ActiveRecord
228
235
  #
229
236
  # Example of a simple migration:
230
237
  #
231
- # class AddSsl < ActiveRecord::Migration[7.0]
238
+ # class AddSsl < ActiveRecord::Migration[7.1]
232
239
  # def up
233
240
  # add_column :accounts, :ssl_enabled, :boolean, default: true
234
241
  # end
@@ -248,7 +255,7 @@ module ActiveRecord
248
255
  #
249
256
  # Example of a more complex migration that also needs to initialize data:
250
257
  #
251
- # class AddSystemSettings < ActiveRecord::Migration[7.0]
258
+ # class AddSystemSettings < ActiveRecord::Migration[7.1]
252
259
  # def up
253
260
  # create_table :system_settings do |t|
254
261
  # t.string :name
@@ -326,7 +333,7 @@ module ActiveRecord
326
333
  # details.
327
334
  # * <tt>change_table(name, options)</tt>: Allows to make column alterations to
328
335
  # the table called +name+. It makes the table object available to a block that
329
- # can then add/remove columns, indexes or foreign keys to it.
336
+ # can then add/remove columns, indexes, or foreign keys to it.
330
337
  # * <tt>rename_column(table_name, column_name, new_column_name)</tt>: Renames
331
338
  # a column but keeps the type and content.
332
339
  # * <tt>rename_index(table_name, old_name, new_name)</tt>: Renames an index.
@@ -356,12 +363,12 @@ module ActiveRecord
356
363
  # == Irreversible transformations
357
364
  #
358
365
  # Some transformations are destructive in a manner that cannot be reversed.
359
- # Migrations of that kind should raise an <tt>ActiveRecord::IrreversibleMigration</tt>
366
+ # Migrations of that kind should raise an ActiveRecord::IrreversibleMigration
360
367
  # exception in their +down+ method.
361
368
  #
362
- # == Running migrations from within Rails
369
+ # == Running migrations from within \Rails
363
370
  #
364
- # The Rails package has several tools to help create and apply migrations.
371
+ # The \Rails package has several tools to help create and apply migrations.
365
372
  #
366
373
  # To generate a new migration, you can use
367
374
  # bin/rails generate migration MyNewMigration
@@ -376,7 +383,7 @@ module ActiveRecord
376
383
  # bin/rails generate migration add_fieldname_to_tablename fieldname:string
377
384
  #
378
385
  # This will generate the file <tt>timestamp_add_fieldname_to_tablename.rb</tt>, which will look like this:
379
- # class AddFieldnameToTablename < ActiveRecord::Migration[7.0]
386
+ # class AddFieldnameToTablename < ActiveRecord::Migration[7.1]
380
387
  # def change
381
388
  # add_column :tablenames, :fieldname, :string
382
389
  # end
@@ -395,14 +402,14 @@ module ActiveRecord
395
402
  # wish to rollback last few migrations. <tt>bin/rails db:rollback STEP=2</tt> will rollback
396
403
  # the latest two migrations.
397
404
  #
398
- # If any of the migrations throw an <tt>ActiveRecord::IrreversibleMigration</tt> exception,
405
+ # If any of the migrations throw an ActiveRecord::IrreversibleMigration exception,
399
406
  # that step will fail and you'll have some manual work to do.
400
407
  #
401
408
  # == More examples
402
409
  #
403
410
  # Not all migrations change the schema. Some just fix the data:
404
411
  #
405
- # class RemoveEmptyTags < ActiveRecord::Migration[7.0]
412
+ # class RemoveEmptyTags < ActiveRecord::Migration[7.1]
406
413
  # def up
407
414
  # Tag.all.each { |tag| tag.destroy if tag.pages.empty? }
408
415
  # end
@@ -415,7 +422,7 @@ module ActiveRecord
415
422
  #
416
423
  # Others remove columns when they migrate up instead of down:
417
424
  #
418
- # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[7.0]
425
+ # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[7.1]
419
426
  # def up
420
427
  # remove_column :items, :incomplete_items_count
421
428
  # remove_column :items, :completed_items_count
@@ -429,7 +436,7 @@ module ActiveRecord
429
436
  #
430
437
  # And sometimes you need to do something in SQL not abstracted directly by migrations:
431
438
  #
432
- # class MakeJoinUnique < ActiveRecord::Migration[7.0]
439
+ # class MakeJoinUnique < ActiveRecord::Migration[7.1]
433
440
  # def up
434
441
  # execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)"
435
442
  # end
@@ -446,7 +453,7 @@ module ActiveRecord
446
453
  # <tt>Base#reset_column_information</tt> in order to ensure that the model has the
447
454
  # latest column data from after the new column was added. Example:
448
455
  #
449
- # class AddPeopleSalary < ActiveRecord::Migration[7.0]
456
+ # class AddPeopleSalary < ActiveRecord::Migration[7.1]
450
457
  # def up
451
458
  # add_column :people, :salary, :integer
452
459
  # Person.reset_column_information
@@ -482,7 +489,7 @@ module ActiveRecord
482
489
  #
483
490
  # == Timestamped Migrations
484
491
  #
485
- # By default, Rails generates migrations that look like:
492
+ # By default, \Rails generates migrations that look like:
486
493
  #
487
494
  # 20080717013526_your_migration_name.rb
488
495
  #
@@ -504,7 +511,7 @@ module ActiveRecord
504
511
  # To define a reversible migration, define the +change+ method in your
505
512
  # migration like this:
506
513
  #
507
- # class TenderloveMigration < ActiveRecord::Migration[7.0]
514
+ # class TenderloveMigration < ActiveRecord::Migration[7.1]
508
515
  # def change
509
516
  # create_table(:horses) do |t|
510
517
  # t.column :content, :text
@@ -521,11 +528,11 @@ module ActiveRecord
521
528
  # as before.
522
529
  #
523
530
  # If a command cannot be reversed, an
524
- # <tt>ActiveRecord::IrreversibleMigration</tt> exception will be raised when
531
+ # ActiveRecord::IrreversibleMigration exception will be raised when
525
532
  # the migration is moving down.
526
533
  #
527
534
  # For a list of commands that are reversible, please see
528
- # <tt>ActiveRecord::Migration::CommandRecorder</tt>.
535
+ # +ActiveRecord::Migration::CommandRecorder+.
529
536
  #
530
537
  # == Transactional Migrations
531
538
  #
@@ -534,7 +541,7 @@ module ActiveRecord
534
541
  # can't execute inside a transaction though, and for these situations
535
542
  # you can turn the automatic transactions off.
536
543
  #
537
- # class ChangeEnum < ActiveRecord::Migration[7.0]
544
+ # class ChangeEnum < ActiveRecord::Migration[7.1]
538
545
  # disable_ddl_transaction!
539
546
  #
540
547
  # def up
@@ -548,9 +555,46 @@ module ActiveRecord
548
555
  autoload :CommandRecorder, "active_record/migration/command_recorder"
549
556
  autoload :Compatibility, "active_record/migration/compatibility"
550
557
  autoload :JoinTable, "active_record/migration/join_table"
558
+ autoload :ExecutionStrategy, "active_record/migration/execution_strategy"
559
+ autoload :DefaultStrategy, "active_record/migration/default_strategy"
551
560
 
552
561
  # This must be defined before the inherited hook, below
553
562
  class Current < Migration # :nodoc:
563
+ def create_table(table_name, **options)
564
+ if block_given?
565
+ super { |t| yield compatible_table_definition(t) }
566
+ else
567
+ super
568
+ end
569
+ end
570
+
571
+ def change_table(table_name, **options)
572
+ if block_given?
573
+ super { |t| yield compatible_table_definition(t) }
574
+ else
575
+ super
576
+ end
577
+ end
578
+
579
+ def create_join_table(table_1, table_2, **options)
580
+ if block_given?
581
+ super { |t| yield compatible_table_definition(t) }
582
+ else
583
+ super
584
+ end
585
+ end
586
+
587
+ def drop_table(table_name, **options)
588
+ if block_given?
589
+ super { |t| yield compatible_table_definition(t) }
590
+ else
591
+ super
592
+ end
593
+ end
594
+
595
+ def compatible_table_definition(t)
596
+ t
597
+ end
554
598
  end
555
599
 
556
600
  def self.inherited(subclass) # :nodoc:
@@ -575,8 +619,15 @@ module ActiveRecord
575
619
 
576
620
  MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/ # :nodoc:
577
621
 
622
+ def self.valid_version_format?(version_string) # :nodoc:
623
+ [
624
+ MigrationFilenameRegexp,
625
+ /\A\d(_?\d)*\z/ # integer with optional underscores
626
+ ].any? { |pattern| pattern.match?(version_string) }
627
+ end
628
+
578
629
  # This class is used to verify that all migrations have been run before
579
- # loading a web page if <tt>config.active_record.migration_error</tt> is set to :page_load
630
+ # loading a web page if <tt>config.active_record.migration_error</tt> is set to +:page_load+.
580
631
  class CheckPending
581
632
  def initialize(app, file_watcher: ActiveSupport::FileUpdateChecker)
582
633
  @app = app
@@ -589,7 +640,7 @@ module ActiveRecord
589
640
  @mutex.synchronize do
590
641
  @watcher ||= build_watcher do
591
642
  @needs_check = true
592
- ActiveRecord::Migration.check_pending!(connection)
643
+ ActiveRecord::Migration.check_pending_migrations
593
644
  @needs_check = false
594
645
  end
595
646
 
@@ -605,12 +656,14 @@ module ActiveRecord
605
656
 
606
657
  private
607
658
  def build_watcher(&block)
608
- paths = Array(connection.migration_context.migrations_paths)
659
+ current_environment = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
660
+ all_configs = ActiveRecord::Base.configurations.configs_for(env_name: current_environment)
661
+ paths = all_configs.flat_map { |config| config.migrations_paths || Migrator.migrations_paths }.uniq
609
662
  @file_watcher.new([], paths.index_with(["rb"]), &block)
610
663
  end
611
664
 
612
665
  def connection
613
- ActiveRecord::Base.connection
666
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection
614
667
  end
615
668
  end
616
669
 
@@ -622,32 +675,53 @@ module ActiveRecord
622
675
  delegate || superclass.nearest_delegate
623
676
  end
624
677
 
625
- # Raises <tt>ActiveRecord::PendingMigrationError</tt> error if any migrations are pending.
626
- def check_pending!(connection = Base.connection)
627
- raise ActiveRecord::PendingMigrationError if connection.migration_context.needs_migration?
678
+ # Raises ActiveRecord::PendingMigrationError error if any migrations are pending.
679
+ #
680
+ # This is deprecated in favor of +check_all_pending!+
681
+ def check_pending!(connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection)
682
+ ActiveRecord.deprecator.warn(<<-MSG.squish)
683
+ The `check_pending!` method is deprecated in favor of `check_all_pending!`. The
684
+ new implementation will loop through all available database configurations and find
685
+ pending migrations. The prior implementation did not permit this.
686
+ MSG
687
+
688
+ pending_migrations = connection.migration_context.open.pending_migrations
689
+
690
+ if pending_migrations.any?
691
+ raise ActiveRecord::PendingMigrationError.new(pending_migrations: pending_migrations)
692
+ end
628
693
  end
629
694
 
630
- def load_schema_if_pending!
631
- current_db_config = Base.connection_db_config
632
- all_configs = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env)
695
+ # Raises ActiveRecord::PendingMigrationError error if any migrations are pending
696
+ # for all database configurations in an environment.
697
+ def check_all_pending!
698
+ pending_migrations = []
633
699
 
634
- needs_update = !all_configs.all? do |db_config|
635
- Tasks::DatabaseTasks.schema_up_to_date?(db_config, ActiveRecord.schema_format)
700
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: env) do |connection|
701
+ if pending = connection.migration_context.open.pending_migrations
702
+ pending_migrations << pending
703
+ end
636
704
  end
637
705
 
638
- if needs_update
706
+ migrations = pending_migrations.flatten
707
+
708
+ if migrations.any?
709
+ raise ActiveRecord::PendingMigrationError.new(pending_migrations: migrations)
710
+ end
711
+ end
712
+
713
+ def load_schema_if_pending!
714
+ if any_schema_needs_update?
639
715
  # Roundtrip to Rake to allow plugins to hook into database initialization.
640
716
  root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
717
+
641
718
  FileUtils.cd(root) do
642
- Base.clear_all_connections!
719
+ Base.connection_handler.clear_all_connections!(:all)
643
720
  system("bin/rails db:test:prepare")
644
721
  end
645
722
  end
646
723
 
647
- # Establish a new connection, the old database may be gone (db:test:prepare uses purge)
648
- Base.establish_connection(current_db_config)
649
-
650
- check_pending!
724
+ check_pending_migrations
651
725
  end
652
726
 
653
727
  def maintain_test_schema! # :nodoc:
@@ -672,6 +746,43 @@ module ActiveRecord
672
746
  def disable_ddl_transaction!
673
747
  @disable_ddl_transaction = true
674
748
  end
749
+
750
+ def check_pending_migrations # :nodoc:
751
+ migrations = pending_migrations
752
+
753
+ if migrations.any?
754
+ raise ActiveRecord::PendingMigrationError.new(pending_migrations: migrations)
755
+ end
756
+ end
757
+
758
+ private
759
+ def any_schema_needs_update?
760
+ !db_configs_in_current_env.all? do |db_config|
761
+ Tasks::DatabaseTasks.schema_up_to_date?(db_config, ActiveRecord.schema_format)
762
+ end
763
+ end
764
+
765
+ def db_configs_in_current_env
766
+ ActiveRecord::Base.configurations.configs_for(env_name: env)
767
+ end
768
+
769
+ def pending_migrations
770
+ pending_migrations = []
771
+
772
+ ActiveRecord::Base.configurations.configs_for(env_name: env).each do |db_config|
773
+ ActiveRecord::PendingMigrationConnection.establish_temporary_connection(db_config) do |conn|
774
+ if pending = conn.migration_context.open.pending_migrations
775
+ pending_migrations << pending
776
+ end
777
+ end
778
+ end
779
+
780
+ pending_migrations.flatten
781
+ end
782
+
783
+ def env
784
+ ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
785
+ end
675
786
  end
676
787
 
677
788
  def disable_ddl_transaction # :nodoc:
@@ -687,6 +798,10 @@ module ActiveRecord
687
798
  @connection = nil
688
799
  end
689
800
 
801
+ def execution_strategy
802
+ @execution_strategy ||= ActiveRecord.migration_strategy.new(self)
803
+ end
804
+
690
805
  self.verbose = true
691
806
  # instantiate the delegate object after initialize is defined
692
807
  self.delegate = new
@@ -698,7 +813,7 @@ module ActiveRecord
698
813
  # and create the table 'apples' on the way up, and the reverse
699
814
  # on the way down.
700
815
  #
701
- # class FixTLMigration < ActiveRecord::Migration[7.0]
816
+ # class FixTLMigration < ActiveRecord::Migration[7.1]
702
817
  # def change
703
818
  # revert do
704
819
  # create_table(:horses) do |t|
@@ -717,7 +832,7 @@ module ActiveRecord
717
832
  #
718
833
  # require_relative "20121212123456_tenderlove_migration"
719
834
  #
720
- # class FixupTLMigration < ActiveRecord::Migration[7.0]
835
+ # class FixupTLMigration < ActiveRecord::Migration[7.1]
721
836
  # def change
722
837
  # revert TenderloveMigration
723
838
  #
@@ -768,7 +883,7 @@ module ActiveRecord
768
883
  # when the three columns 'first_name', 'last_name' and 'full_name' exist,
769
884
  # even when migrating down:
770
885
  #
771
- # class SplitNameMigration < ActiveRecord::Migration[7.0]
886
+ # class SplitNameMigration < ActiveRecord::Migration[7.1]
772
887
  # def change
773
888
  # add_column :users, :first_name, :string
774
889
  # add_column :users, :last_name, :string
@@ -796,7 +911,7 @@ module ActiveRecord
796
911
  # In the following example, the new column +published+ will be given
797
912
  # the value +true+ for all existing records.
798
913
  #
799
- # class AddPublishedToPosts < ActiveRecord::Migration[7.0]
914
+ # class AddPublishedToPosts < ActiveRecord::Migration[7.1]
800
915
  # def change
801
916
  # add_column :posts, :published, :boolean, default: false
802
917
  # up_only do
@@ -810,8 +925,9 @@ module ActiveRecord
810
925
 
811
926
  # Runs the given migration classes.
812
927
  # Last argument can specify options:
813
- # - :direction (default is :up)
814
- # - :revert (default is false)
928
+ #
929
+ # - +:direction+ - Default is +:up+.
930
+ # - +:revert+ - Default is +false+.
815
931
  def run(*migration_classes)
816
932
  opts = migration_classes.extract_options!
817
933
  dir = opts[:direction] || :up
@@ -848,7 +964,7 @@ module ActiveRecord
848
964
  end
849
965
 
850
966
  time = nil
851
- ActiveRecord::Base.connection_pool.with_connection do |conn|
967
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection.pool.with_connection do |conn|
852
968
  time = Benchmark.measure do
853
969
  exec_migration(conn, direction)
854
970
  end
@@ -873,6 +989,7 @@ module ActiveRecord
873
989
  end
874
990
  ensure
875
991
  @connection = nil
992
+ @execution_strategy = nil
876
993
  end
877
994
 
878
995
  def write(text = "")
@@ -911,13 +1028,11 @@ module ActiveRecord
911
1028
  end
912
1029
 
913
1030
  def connection
914
- @connection || ActiveRecord::Base.connection
1031
+ @connection || ActiveRecord::Tasks::DatabaseTasks.migration_connection
915
1032
  end
916
1033
 
917
1034
  def method_missing(method, *arguments, &block)
918
- arg_list = arguments.map(&:inspect) * ", "
919
-
920
- say_with_time "#{method}(#{arg_list})" do
1035
+ say_with_time "#{method}(#{format_arguments(arguments)})" do
921
1036
  unless connection.respond_to? :revert
922
1037
  unless arguments.empty? || [:execute, :enable_extension, :disable_extension].include?(method)
923
1038
  arguments[0] = proper_table_name(arguments.first, table_name_options)
@@ -927,22 +1042,23 @@ module ActiveRecord
927
1042
  end
928
1043
  end
929
1044
  end
930
- return super unless connection.respond_to?(method)
931
- connection.send(method, *arguments, &block)
1045
+ return super unless execution_strategy.respond_to?(method)
1046
+ execution_strategy.send(method, *arguments, &block)
932
1047
  end
933
1048
  end
934
1049
  ruby2_keywords(:method_missing)
935
1050
 
936
1051
  def copy(destination, sources, options = {})
937
1052
  copied = []
938
- schema_migration = options[:schema_migration] || ActiveRecord::SchemaMigration
939
1053
 
940
1054
  FileUtils.mkdir_p(destination) unless File.exist?(destination)
1055
+ schema_migration = SchemaMigration::NullSchemaMigration.new
1056
+ internal_metadata = InternalMetadata::NullInternalMetadata.new
941
1057
 
942
- destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration).migrations
1058
+ destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration, internal_metadata).migrations
943
1059
  last = destination_migrations.last
944
1060
  sources.each do |scope, path|
945
- source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration).migrations
1061
+ source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration, internal_metadata).migrations
946
1062
 
947
1063
  source_migrations.each do |migration|
948
1064
  source = File.binread(migration.filename)
@@ -1001,9 +1117,9 @@ module ActiveRecord
1001
1117
  # Determines the version number of the next migration.
1002
1118
  def next_migration_number(number)
1003
1119
  if ActiveRecord.timestamped_migrations
1004
- [Time.now.utc.strftime("%Y%m%d%H%M%S").to_i, ("%.14d" % number).to_i].max
1120
+ [Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max
1005
1121
  else
1006
- SchemaMigration.normalize_migration_number(number)
1122
+ "%.3d" % number.to_i
1007
1123
  end
1008
1124
  end
1009
1125
 
@@ -1025,6 +1141,22 @@ module ActiveRecord
1025
1141
  end
1026
1142
  end
1027
1143
 
1144
+ def format_arguments(arguments)
1145
+ arg_list = arguments[0...-1].map(&:inspect)
1146
+ last_arg = arguments.last
1147
+ if last_arg.is_a?(Hash)
1148
+ last_arg = last_arg.reject { |k, _v| internal_option?(k) }
1149
+ arg_list << last_arg.inspect unless last_arg.empty?
1150
+ else
1151
+ arg_list << last_arg.inspect
1152
+ end
1153
+ arg_list.join(", ")
1154
+ end
1155
+
1156
+ def internal_option?(option_name)
1157
+ option_name.start_with?("_")
1158
+ end
1159
+
1028
1160
  def command_recorder
1029
1161
  CommandRecorder.new(connection)
1030
1162
  end
@@ -1057,19 +1189,44 @@ module ActiveRecord
1057
1189
  end
1058
1190
  end
1059
1191
 
1192
+ # = \Migration \Context
1193
+ #
1060
1194
  # MigrationContext sets the context in which a migration is run.
1061
1195
  #
1062
1196
  # A migration context requires the path to the migrations is set
1063
1197
  # in the +migrations_paths+ parameter. Optionally a +schema_migration+
1064
- # class can be provided. For most applications, +SchemaMigration+ is
1065
- # sufficient. Multiple database applications need a +SchemaMigration+
1066
- # per primary database.
1198
+ # class can be provided. Multiple database applications will instantiate
1199
+ # a +SchemaMigration+ object per database. From the Rake tasks, \Rails will
1200
+ # handle this for you.
1067
1201
  class MigrationContext
1068
- attr_reader :migrations_paths, :schema_migration
1202
+ attr_reader :migrations_paths, :schema_migration, :internal_metadata
1203
+
1204
+ def initialize(migrations_paths, schema_migration = nil, internal_metadata = nil)
1205
+ if schema_migration == SchemaMigration
1206
+ ActiveRecord.deprecator.warn(<<-MSG.squish)
1207
+ SchemaMigration no longer inherits from ActiveRecord::Base. If you want
1208
+ to use the default connection, remove this argument. If you want to use a
1209
+ specific connection, instantiate MigrationContext with the connection's schema
1210
+ migration, for example `MigrationContext.new(path, Dog.connection.schema_migration)`.
1211
+ MSG
1212
+
1213
+ schema_migration = nil
1214
+ end
1215
+
1216
+ if internal_metadata == InternalMetadata
1217
+ ActiveRecord.deprecator.warn(<<-MSG.squish)
1218
+ SchemaMigration no longer inherits from ActiveRecord::Base. If you want
1219
+ to use the default connection, remove this argument. If you want to use a
1220
+ specific connection, instantiate MigrationContext with the connection's internal
1221
+ metadata, for example `MigrationContext.new(path, nil, Dog.connection.internal_metadata)`.
1222
+ MSG
1223
+
1224
+ internal_metadata = nil
1225
+ end
1069
1226
 
1070
- def initialize(migrations_paths, schema_migration = SchemaMigration)
1071
1227
  @migrations_paths = migrations_paths
1072
- @schema_migration = schema_migration
1228
+ @schema_migration = schema_migration || SchemaMigration.new(connection)
1229
+ @internal_metadata = internal_metadata || InternalMetadata.new(connection)
1073
1230
  end
1074
1231
 
1075
1232
  # Runs the migrations in the +migrations_path+.
@@ -1113,7 +1270,7 @@ module ActiveRecord
1113
1270
  migrations
1114
1271
  end
1115
1272
 
1116
- Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate
1273
+ Migrator.new(:up, selected_migrations, schema_migration, internal_metadata, target_version).migrate
1117
1274
  end
1118
1275
 
1119
1276
  def down(target_version = nil, &block) # :nodoc:
@@ -1123,20 +1280,20 @@ module ActiveRecord
1123
1280
  migrations
1124
1281
  end
1125
1282
 
1126
- Migrator.new(:down, selected_migrations, schema_migration, target_version).migrate
1283
+ Migrator.new(:down, selected_migrations, schema_migration, internal_metadata, target_version).migrate
1127
1284
  end
1128
1285
 
1129
1286
  def run(direction, target_version) # :nodoc:
1130
- Migrator.new(direction, migrations, schema_migration, target_version).run
1287
+ Migrator.new(direction, migrations, schema_migration, internal_metadata, target_version).run
1131
1288
  end
1132
1289
 
1133
1290
  def open # :nodoc:
1134
- Migrator.new(:up, migrations, schema_migration)
1291
+ Migrator.new(:up, migrations, schema_migration, internal_metadata)
1135
1292
  end
1136
1293
 
1137
1294
  def get_all_versions # :nodoc:
1138
1295
  if schema_migration.table_exists?
1139
- schema_migration.all_versions.map(&:to_i)
1296
+ schema_migration.integer_versions
1140
1297
  else
1141
1298
  []
1142
1299
  end
@@ -1195,16 +1352,20 @@ module ActiveRecord
1195
1352
  end
1196
1353
 
1197
1354
  def last_stored_environment # :nodoc:
1198
- return nil unless ActiveRecord::InternalMetadata.enabled?
1355
+ return nil unless connection.internal_metadata.enabled?
1199
1356
  return nil if current_version == 0
1200
- raise NoEnvironmentInSchemaError unless ActiveRecord::InternalMetadata.table_exists?
1357
+ raise NoEnvironmentInSchemaError unless connection.internal_metadata.table_exists?
1201
1358
 
1202
- environment = ActiveRecord::InternalMetadata[:environment]
1359
+ environment = connection.internal_metadata[:environment]
1203
1360
  raise NoEnvironmentInSchemaError unless environment
1204
1361
  environment
1205
1362
  end
1206
1363
 
1207
1364
  private
1365
+ def connection
1366
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection
1367
+ end
1368
+
1208
1369
  def migration_files
1209
1370
  paths = Array(migrations_paths)
1210
1371
  Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
@@ -1215,7 +1376,7 @@ module ActiveRecord
1215
1376
  end
1216
1377
 
1217
1378
  def move(direction, steps)
1218
- migrator = Migrator.new(direction, migrations, schema_migration)
1379
+ migrator = Migrator.new(direction, migrations, schema_migration, internal_metadata)
1219
1380
 
1220
1381
  if current_version != 0 && !migrator.current_migration
1221
1382
  raise UnknownMigrationVersionError.new(current_version)
@@ -1240,23 +1401,28 @@ module ActiveRecord
1240
1401
 
1241
1402
  # For cases where a table doesn't exist like loading from schema cache
1242
1403
  def current_version
1243
- MigrationContext.new(migrations_paths, SchemaMigration).current_version
1404
+ connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection
1405
+ schema_migration = SchemaMigration.new(connection)
1406
+ internal_metadata = InternalMetadata.new(connection)
1407
+
1408
+ MigrationContext.new(migrations_paths, schema_migration, internal_metadata).current_version
1244
1409
  end
1245
1410
  end
1246
1411
 
1247
1412
  self.migrations_paths = ["db/migrate"]
1248
1413
 
1249
- def initialize(direction, migrations, schema_migration, target_version = nil)
1414
+ def initialize(direction, migrations, schema_migration, internal_metadata, target_version = nil)
1250
1415
  @direction = direction
1251
1416
  @target_version = target_version
1252
1417
  @migrated_versions = nil
1253
1418
  @migrations = migrations
1254
1419
  @schema_migration = schema_migration
1420
+ @internal_metadata = internal_metadata
1255
1421
 
1256
1422
  validate(@migrations)
1257
1423
 
1258
1424
  @schema_migration.create_table
1259
- ActiveRecord::InternalMetadata.create_table
1425
+ @internal_metadata.create_table
1260
1426
  end
1261
1427
 
1262
1428
  def current_version
@@ -1309,18 +1475,21 @@ module ActiveRecord
1309
1475
  end
1310
1476
 
1311
1477
  def load_migrated
1312
- @migrated_versions = Set.new(@schema_migration.all_versions.map(&:to_i))
1478
+ @migrated_versions = Set.new(@schema_migration.integer_versions)
1313
1479
  end
1314
1480
 
1315
1481
  private
1482
+ def connection
1483
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection
1484
+ end
1485
+
1316
1486
  # Used for running a specific migration.
1317
1487
  def run_without_lock
1318
1488
  migration = migrations.detect { |m| m.version == @target_version }
1319
1489
  raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
1320
- result = execute_migration_in_transaction(migration)
1321
1490
 
1322
1491
  record_environment
1323
- result
1492
+ execute_migration_in_transaction(migration)
1324
1493
  end
1325
1494
 
1326
1495
  # Used for running multiple migrations up to or down to a certain value.
@@ -1329,15 +1498,15 @@ module ActiveRecord
1329
1498
  raise UnknownMigrationVersionError.new(@target_version)
1330
1499
  end
1331
1500
 
1332
- result = runnable.each(&method(:execute_migration_in_transaction))
1333
1501
  record_environment
1334
- result
1502
+ runnable.each(&method(:execute_migration_in_transaction))
1335
1503
  end
1336
1504
 
1337
1505
  # Stores the current environment in the database.
1338
1506
  def record_environment
1339
1507
  return if down?
1340
- ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Base.connection.migration_context.current_environment
1508
+
1509
+ @internal_metadata[:environment] = connection.pool.db_config.env_name
1341
1510
  end
1342
1511
 
1343
1512
  def ran?(migration)
@@ -1389,10 +1558,10 @@ module ActiveRecord
1389
1558
  def record_version_state_after_migrating(version)
1390
1559
  if down?
1391
1560
  migrated.delete(version)
1392
- @schema_migration.delete_by(version: version.to_s)
1561
+ @schema_migration.delete_version(version.to_s)
1393
1562
  else
1394
1563
  migrated << version
1395
- @schema_migration.create!(version: version.to_s)
1564
+ @schema_migration.create_version(version.to_s)
1396
1565
  end
1397
1566
  end
1398
1567
 
@@ -1407,50 +1576,38 @@ module ActiveRecord
1407
1576
  # Wrap the migration in a transaction only if supported by the adapter.
1408
1577
  def ddl_transaction(migration, &block)
1409
1578
  if use_transaction?(migration)
1410
- Base.transaction(&block)
1579
+ connection.transaction(&block)
1411
1580
  else
1412
1581
  yield
1413
1582
  end
1414
1583
  end
1415
1584
 
1416
1585
  def use_transaction?(migration)
1417
- !migration.disable_ddl_transaction && Base.connection.supports_ddl_transactions?
1586
+ !migration.disable_ddl_transaction && connection.supports_ddl_transactions?
1418
1587
  end
1419
1588
 
1420
1589
  def use_advisory_lock?
1421
- Base.connection.advisory_locks_enabled?
1590
+ connection.advisory_locks_enabled?
1422
1591
  end
1423
1592
 
1424
1593
  def with_advisory_lock
1425
1594
  lock_id = generate_migrator_advisory_lock_id
1426
1595
 
1427
- with_advisory_lock_connection do |connection|
1428
- got_lock = connection.get_advisory_lock(lock_id)
1429
- raise ConcurrentMigrationError unless got_lock
1430
- load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
1431
- yield
1432
- ensure
1433
- if got_lock && !connection.release_advisory_lock(lock_id)
1434
- raise ConcurrentMigrationError.new(
1435
- ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
1436
- )
1437
- end
1438
- end
1439
- end
1440
-
1441
- def with_advisory_lock_connection(&block)
1442
- pool = ActiveRecord::ConnectionAdapters::ConnectionHandler.new.establish_connection(
1443
- ActiveRecord::Base.connection_db_config
1444
- )
1445
-
1446
- pool.with_connection(&block)
1596
+ got_lock = connection.get_advisory_lock(lock_id)
1597
+ raise ConcurrentMigrationError unless got_lock
1598
+ load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
1599
+ yield
1447
1600
  ensure
1448
- pool&.disconnect!
1601
+ if got_lock && !connection.release_advisory_lock(lock_id)
1602
+ raise ConcurrentMigrationError.new(
1603
+ ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
1604
+ )
1605
+ end
1449
1606
  end
1450
1607
 
1451
1608
  MIGRATOR_SALT = 2053462845
1452
1609
  def generate_migrator_advisory_lock_id
1453
- db_name_hash = Zlib.crc32(Base.connection.current_database)
1610
+ db_name_hash = Zlib.crc32(connection.current_database)
1454
1611
  MIGRATOR_SALT * db_name_hash
1455
1612
  end
1456
1613
  end