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.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

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
@@ -20,7 +20,7 @@ module ActiveRecord
20
20
  # For example the following migration is not reversible.
21
21
  # Rolling back this migration will raise an ActiveRecord::IrreversibleMigration error.
22
22
  #
23
- # class IrreversibleMigrationExample < ActiveRecord::Migration[7.0]
23
+ # class IrreversibleMigrationExample < ActiveRecord::Migration[7.1]
24
24
  # def change
25
25
  # create_table :distributors do |t|
26
26
  # t.string :zipcode
@@ -38,7 +38,7 @@ module ActiveRecord
38
38
  #
39
39
  # 1. Define <tt>#up</tt> and <tt>#down</tt> methods instead of <tt>#change</tt>:
40
40
  #
41
- # class ReversibleMigrationExample < ActiveRecord::Migration[7.0]
41
+ # class ReversibleMigrationExample < ActiveRecord::Migration[7.1]
42
42
  # def up
43
43
  # create_table :distributors do |t|
44
44
  # t.string :zipcode
@@ -63,7 +63,7 @@ module ActiveRecord
63
63
  #
64
64
  # 2. Use the #reversible method in <tt>#change</tt> method:
65
65
  #
66
- # class ReversibleMigrationExample < ActiveRecord::Migration[7.0]
66
+ # class ReversibleMigrationExample < ActiveRecord::Migration[7.1]
67
67
  # def change
68
68
  # create_table :distributors do |t|
69
69
  # t.string :zipcode
@@ -137,32 +137,38 @@ module ActiveRecord
137
137
  ActiveRecord::Tasks::DatabaseTasks.migrate
138
138
 
139
139
  if ActiveRecord.dump_schema_after_migration
140
- ActiveRecord::Tasks::DatabaseTasks.dump_schema(
141
- ActiveRecord::Base.connection_db_config
142
- )
140
+ connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection
141
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema(connection.pool.db_config)
143
142
  end
144
143
  end
145
144
 
146
- def initialize(message = nil)
147
- super(message || detailed_migration_message)
145
+ def initialize(message = nil, pending_migrations: nil)
146
+ if pending_migrations.nil?
147
+ connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection
148
+ pending_migrations = connection.migration_context.open.pending_migrations
149
+ end
150
+
151
+ super(message || detailed_migration_message(pending_migrations))
148
152
  end
149
153
 
150
154
  private
151
- def detailed_migration_message
155
+ def detailed_migration_message(pending_migrations)
152
156
  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)
157
+ message += " RAILS_ENV=#{::Rails.env}" if defined?(Rails.env) && !Rails.env.local?
154
158
  message += "\n\n"
155
159
 
156
- pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations
157
-
158
160
  message += "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}\n\n"
159
161
 
160
162
  pending_migrations.each do |pending_migration|
161
- message += "#{pending_migration.basename}\n"
163
+ message += "#{pending_migration.filename}\n"
162
164
  end
163
165
 
164
166
  message
165
167
  end
168
+
169
+ def connection
170
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection
171
+ end
166
172
  end
167
173
 
168
174
  class ConcurrentMigrationError < MigrationError # :nodoc:
@@ -228,7 +234,7 @@ module ActiveRecord
228
234
  #
229
235
  # Example of a simple migration:
230
236
  #
231
- # class AddSsl < ActiveRecord::Migration[7.0]
237
+ # class AddSsl < ActiveRecord::Migration[7.1]
232
238
  # def up
233
239
  # add_column :accounts, :ssl_enabled, :boolean, default: true
234
240
  # end
@@ -248,7 +254,7 @@ module ActiveRecord
248
254
  #
249
255
  # Example of a more complex migration that also needs to initialize data:
250
256
  #
251
- # class AddSystemSettings < ActiveRecord::Migration[7.0]
257
+ # class AddSystemSettings < ActiveRecord::Migration[7.1]
252
258
  # def up
253
259
  # create_table :system_settings do |t|
254
260
  # t.string :name
@@ -326,7 +332,7 @@ module ActiveRecord
326
332
  # details.
327
333
  # * <tt>change_table(name, options)</tt>: Allows to make column alterations to
328
334
  # 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.
335
+ # can then add/remove columns, indexes, or foreign keys to it.
330
336
  # * <tt>rename_column(table_name, column_name, new_column_name)</tt>: Renames
331
337
  # a column but keeps the type and content.
332
338
  # * <tt>rename_index(table_name, old_name, new_name)</tt>: Renames an index.
@@ -356,12 +362,12 @@ module ActiveRecord
356
362
  # == Irreversible transformations
357
363
  #
358
364
  # Some transformations are destructive in a manner that cannot be reversed.
359
- # Migrations of that kind should raise an <tt>ActiveRecord::IrreversibleMigration</tt>
365
+ # Migrations of that kind should raise an ActiveRecord::IrreversibleMigration
360
366
  # exception in their +down+ method.
361
367
  #
362
- # == Running migrations from within Rails
368
+ # == Running migrations from within \Rails
363
369
  #
364
- # The Rails package has several tools to help create and apply migrations.
370
+ # The \Rails package has several tools to help create and apply migrations.
365
371
  #
366
372
  # To generate a new migration, you can use
367
373
  # bin/rails generate migration MyNewMigration
@@ -376,7 +382,7 @@ module ActiveRecord
376
382
  # bin/rails generate migration add_fieldname_to_tablename fieldname:string
377
383
  #
378
384
  # 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]
385
+ # class AddFieldnameToTablename < ActiveRecord::Migration[7.1]
380
386
  # def change
381
387
  # add_column :tablenames, :fieldname, :string
382
388
  # end
@@ -395,14 +401,14 @@ module ActiveRecord
395
401
  # wish to rollback last few migrations. <tt>bin/rails db:rollback STEP=2</tt> will rollback
396
402
  # the latest two migrations.
397
403
  #
398
- # If any of the migrations throw an <tt>ActiveRecord::IrreversibleMigration</tt> exception,
404
+ # If any of the migrations throw an ActiveRecord::IrreversibleMigration exception,
399
405
  # that step will fail and you'll have some manual work to do.
400
406
  #
401
407
  # == More examples
402
408
  #
403
409
  # Not all migrations change the schema. Some just fix the data:
404
410
  #
405
- # class RemoveEmptyTags < ActiveRecord::Migration[7.0]
411
+ # class RemoveEmptyTags < ActiveRecord::Migration[7.1]
406
412
  # def up
407
413
  # Tag.all.each { |tag| tag.destroy if tag.pages.empty? }
408
414
  # end
@@ -415,7 +421,7 @@ module ActiveRecord
415
421
  #
416
422
  # Others remove columns when they migrate up instead of down:
417
423
  #
418
- # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[7.0]
424
+ # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[7.1]
419
425
  # def up
420
426
  # remove_column :items, :incomplete_items_count
421
427
  # remove_column :items, :completed_items_count
@@ -429,7 +435,7 @@ module ActiveRecord
429
435
  #
430
436
  # And sometimes you need to do something in SQL not abstracted directly by migrations:
431
437
  #
432
- # class MakeJoinUnique < ActiveRecord::Migration[7.0]
438
+ # class MakeJoinUnique < ActiveRecord::Migration[7.1]
433
439
  # def up
434
440
  # execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)"
435
441
  # end
@@ -446,7 +452,7 @@ module ActiveRecord
446
452
  # <tt>Base#reset_column_information</tt> in order to ensure that the model has the
447
453
  # latest column data from after the new column was added. Example:
448
454
  #
449
- # class AddPeopleSalary < ActiveRecord::Migration[7.0]
455
+ # class AddPeopleSalary < ActiveRecord::Migration[7.1]
450
456
  # def up
451
457
  # add_column :people, :salary, :integer
452
458
  # Person.reset_column_information
@@ -482,7 +488,7 @@ module ActiveRecord
482
488
  #
483
489
  # == Timestamped Migrations
484
490
  #
485
- # By default, Rails generates migrations that look like:
491
+ # By default, \Rails generates migrations that look like:
486
492
  #
487
493
  # 20080717013526_your_migration_name.rb
488
494
  #
@@ -504,7 +510,7 @@ module ActiveRecord
504
510
  # To define a reversible migration, define the +change+ method in your
505
511
  # migration like this:
506
512
  #
507
- # class TenderloveMigration < ActiveRecord::Migration[7.0]
513
+ # class TenderloveMigration < ActiveRecord::Migration[7.1]
508
514
  # def change
509
515
  # create_table(:horses) do |t|
510
516
  # t.column :content, :text
@@ -521,11 +527,11 @@ module ActiveRecord
521
527
  # as before.
522
528
  #
523
529
  # If a command cannot be reversed, an
524
- # <tt>ActiveRecord::IrreversibleMigration</tt> exception will be raised when
530
+ # ActiveRecord::IrreversibleMigration exception will be raised when
525
531
  # the migration is moving down.
526
532
  #
527
533
  # For a list of commands that are reversible, please see
528
- # <tt>ActiveRecord::Migration::CommandRecorder</tt>.
534
+ # +ActiveRecord::Migration::CommandRecorder+.
529
535
  #
530
536
  # == Transactional Migrations
531
537
  #
@@ -534,7 +540,7 @@ module ActiveRecord
534
540
  # can't execute inside a transaction though, and for these situations
535
541
  # you can turn the automatic transactions off.
536
542
  #
537
- # class ChangeEnum < ActiveRecord::Migration[7.0]
543
+ # class ChangeEnum < ActiveRecord::Migration[7.1]
538
544
  # disable_ddl_transaction!
539
545
  #
540
546
  # def up
@@ -548,9 +554,46 @@ module ActiveRecord
548
554
  autoload :CommandRecorder, "active_record/migration/command_recorder"
549
555
  autoload :Compatibility, "active_record/migration/compatibility"
550
556
  autoload :JoinTable, "active_record/migration/join_table"
557
+ autoload :ExecutionStrategy, "active_record/migration/execution_strategy"
558
+ autoload :DefaultStrategy, "active_record/migration/default_strategy"
551
559
 
552
560
  # This must be defined before the inherited hook, below
553
561
  class Current < Migration # :nodoc:
562
+ def create_table(table_name, **options)
563
+ if block_given?
564
+ super { |t| yield compatible_table_definition(t) }
565
+ else
566
+ super
567
+ end
568
+ end
569
+
570
+ def change_table(table_name, **options)
571
+ if block_given?
572
+ super { |t| yield compatible_table_definition(t) }
573
+ else
574
+ super
575
+ end
576
+ end
577
+
578
+ def create_join_table(table_1, table_2, **options)
579
+ if block_given?
580
+ super { |t| yield compatible_table_definition(t) }
581
+ else
582
+ super
583
+ end
584
+ end
585
+
586
+ def drop_table(table_name, **options)
587
+ if block_given?
588
+ super { |t| yield compatible_table_definition(t) }
589
+ else
590
+ super
591
+ end
592
+ end
593
+
594
+ def compatible_table_definition(t)
595
+ t
596
+ end
554
597
  end
555
598
 
556
599
  def self.inherited(subclass) # :nodoc:
@@ -575,8 +618,15 @@ module ActiveRecord
575
618
 
576
619
  MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/ # :nodoc:
577
620
 
621
+ def self.valid_version_format?(version_string) # :nodoc:
622
+ [
623
+ MigrationFilenameRegexp,
624
+ /\A\d(_?\d)*\z/ # integer with optional underscores
625
+ ].any? { |pattern| pattern.match?(version_string) }
626
+ end
627
+
578
628
  # 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
629
+ # loading a web page if <tt>config.active_record.migration_error</tt> is set to +:page_load+.
580
630
  class CheckPending
581
631
  def initialize(app, file_watcher: ActiveSupport::FileUpdateChecker)
582
632
  @app = app
@@ -589,7 +639,7 @@ module ActiveRecord
589
639
  @mutex.synchronize do
590
640
  @watcher ||= build_watcher do
591
641
  @needs_check = true
592
- ActiveRecord::Migration.check_pending!(connection)
642
+ ActiveRecord::Migration.check_pending_migrations
593
643
  @needs_check = false
594
644
  end
595
645
 
@@ -605,12 +655,14 @@ module ActiveRecord
605
655
 
606
656
  private
607
657
  def build_watcher(&block)
608
- paths = Array(connection.migration_context.migrations_paths)
658
+ current_environment = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
659
+ all_configs = ActiveRecord::Base.configurations.configs_for(env_name: current_environment)
660
+ paths = all_configs.flat_map { |config| config.migrations_paths || Migrator.migrations_paths }.uniq
609
661
  @file_watcher.new([], paths.index_with(["rb"]), &block)
610
662
  end
611
663
 
612
664
  def connection
613
- ActiveRecord::Base.connection
665
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection
614
666
  end
615
667
  end
616
668
 
@@ -622,32 +674,53 @@ module ActiveRecord
622
674
  delegate || superclass.nearest_delegate
623
675
  end
624
676
 
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?
677
+ # Raises ActiveRecord::PendingMigrationError error if any migrations are pending.
678
+ #
679
+ # This is deprecated in favor of +check_all_pending!+
680
+ def check_pending!(connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection)
681
+ ActiveRecord.deprecator.warn(<<-MSG.squish)
682
+ The `check_pending!` method is deprecated in favor of `check_all_pending!`. The
683
+ new implementation will loop through all available database configurations and find
684
+ pending migrations. The prior implementation did not permit this.
685
+ MSG
686
+
687
+ pending_migrations = connection.migration_context.open.pending_migrations
688
+
689
+ if pending_migrations.any?
690
+ raise ActiveRecord::PendingMigrationError.new(pending_migrations: pending_migrations)
691
+ end
628
692
  end
629
693
 
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)
694
+ # Raises ActiveRecord::PendingMigrationError error if any migrations are pending
695
+ # for all database configurations in an environment.
696
+ def check_all_pending!
697
+ pending_migrations = []
633
698
 
634
- needs_update = !all_configs.all? do |db_config|
635
- Tasks::DatabaseTasks.schema_up_to_date?(db_config, ActiveRecord.schema_format)
699
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: env) do |connection|
700
+ if pending = connection.migration_context.open.pending_migrations
701
+ pending_migrations << pending
702
+ end
636
703
  end
637
704
 
638
- if needs_update
705
+ migrations = pending_migrations.flatten
706
+
707
+ if migrations.any?
708
+ raise ActiveRecord::PendingMigrationError.new(pending_migrations: migrations)
709
+ end
710
+ end
711
+
712
+ def load_schema_if_pending!
713
+ if any_schema_needs_update?
639
714
  # Roundtrip to Rake to allow plugins to hook into database initialization.
640
715
  root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
716
+
641
717
  FileUtils.cd(root) do
642
- Base.clear_all_connections!
718
+ Base.connection_handler.clear_all_connections!(:all)
643
719
  system("bin/rails db:test:prepare")
644
720
  end
645
721
  end
646
722
 
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!
723
+ check_pending_migrations
651
724
  end
652
725
 
653
726
  def maintain_test_schema! # :nodoc:
@@ -672,6 +745,41 @@ module ActiveRecord
672
745
  def disable_ddl_transaction!
673
746
  @disable_ddl_transaction = true
674
747
  end
748
+
749
+ def check_pending_migrations # :nodoc:
750
+ migrations = pending_migrations
751
+
752
+ if migrations.any?
753
+ raise ActiveRecord::PendingMigrationError.new(pending_migrations: migrations)
754
+ end
755
+ end
756
+
757
+ private
758
+ def any_schema_needs_update?
759
+ !db_configs_in_current_env.all? do |db_config|
760
+ Tasks::DatabaseTasks.schema_up_to_date?(db_config, ActiveRecord.schema_format)
761
+ end
762
+ end
763
+
764
+ def db_configs_in_current_env
765
+ ActiveRecord::Base.configurations.configs_for(env_name: env)
766
+ end
767
+
768
+ def pending_migrations
769
+ pending_migrations = []
770
+
771
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: env) do |connection|
772
+ if pending = connection.migration_context.open.pending_migrations
773
+ pending_migrations << pending
774
+ end
775
+ end
776
+
777
+ pending_migrations.flatten
778
+ end
779
+
780
+ def env
781
+ ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
782
+ end
675
783
  end
676
784
 
677
785
  def disable_ddl_transaction # :nodoc:
@@ -687,6 +795,10 @@ module ActiveRecord
687
795
  @connection = nil
688
796
  end
689
797
 
798
+ def execution_strategy
799
+ @execution_strategy ||= ActiveRecord.migration_strategy.new(self)
800
+ end
801
+
690
802
  self.verbose = true
691
803
  # instantiate the delegate object after initialize is defined
692
804
  self.delegate = new
@@ -698,7 +810,7 @@ module ActiveRecord
698
810
  # and create the table 'apples' on the way up, and the reverse
699
811
  # on the way down.
700
812
  #
701
- # class FixTLMigration < ActiveRecord::Migration[7.0]
813
+ # class FixTLMigration < ActiveRecord::Migration[7.1]
702
814
  # def change
703
815
  # revert do
704
816
  # create_table(:horses) do |t|
@@ -717,7 +829,7 @@ module ActiveRecord
717
829
  #
718
830
  # require_relative "20121212123456_tenderlove_migration"
719
831
  #
720
- # class FixupTLMigration < ActiveRecord::Migration[7.0]
832
+ # class FixupTLMigration < ActiveRecord::Migration[7.1]
721
833
  # def change
722
834
  # revert TenderloveMigration
723
835
  #
@@ -768,7 +880,7 @@ module ActiveRecord
768
880
  # when the three columns 'first_name', 'last_name' and 'full_name' exist,
769
881
  # even when migrating down:
770
882
  #
771
- # class SplitNameMigration < ActiveRecord::Migration[7.0]
883
+ # class SplitNameMigration < ActiveRecord::Migration[7.1]
772
884
  # def change
773
885
  # add_column :users, :first_name, :string
774
886
  # add_column :users, :last_name, :string
@@ -796,7 +908,7 @@ module ActiveRecord
796
908
  # In the following example, the new column +published+ will be given
797
909
  # the value +true+ for all existing records.
798
910
  #
799
- # class AddPublishedToPosts < ActiveRecord::Migration[7.0]
911
+ # class AddPublishedToPosts < ActiveRecord::Migration[7.1]
800
912
  # def change
801
913
  # add_column :posts, :published, :boolean, default: false
802
914
  # up_only do
@@ -810,8 +922,9 @@ module ActiveRecord
810
922
 
811
923
  # Runs the given migration classes.
812
924
  # Last argument can specify options:
813
- # - :direction (default is :up)
814
- # - :revert (default is false)
925
+ #
926
+ # - +:direction+ - Default is +:up+.
927
+ # - +:revert+ - Default is +false+.
815
928
  def run(*migration_classes)
816
929
  opts = migration_classes.extract_options!
817
930
  dir = opts[:direction] || :up
@@ -848,7 +961,7 @@ module ActiveRecord
848
961
  end
849
962
 
850
963
  time = nil
851
- ActiveRecord::Base.connection_pool.with_connection do |conn|
964
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection.pool.with_connection do |conn|
852
965
  time = Benchmark.measure do
853
966
  exec_migration(conn, direction)
854
967
  end
@@ -873,6 +986,7 @@ module ActiveRecord
873
986
  end
874
987
  ensure
875
988
  @connection = nil
989
+ @execution_strategy = nil
876
990
  end
877
991
 
878
992
  def write(text = "")
@@ -911,13 +1025,11 @@ module ActiveRecord
911
1025
  end
912
1026
 
913
1027
  def connection
914
- @connection || ActiveRecord::Base.connection
1028
+ @connection || ActiveRecord::Tasks::DatabaseTasks.migration_connection
915
1029
  end
916
1030
 
917
1031
  def method_missing(method, *arguments, &block)
918
- arg_list = arguments.map(&:inspect) * ", "
919
-
920
- say_with_time "#{method}(#{arg_list})" do
1032
+ say_with_time "#{method}(#{format_arguments(arguments)})" do
921
1033
  unless connection.respond_to? :revert
922
1034
  unless arguments.empty? || [:execute, :enable_extension, :disable_extension].include?(method)
923
1035
  arguments[0] = proper_table_name(arguments.first, table_name_options)
@@ -927,22 +1039,23 @@ module ActiveRecord
927
1039
  end
928
1040
  end
929
1041
  end
930
- return super unless connection.respond_to?(method)
931
- connection.send(method, *arguments, &block)
1042
+ return super unless execution_strategy.respond_to?(method)
1043
+ execution_strategy.send(method, *arguments, &block)
932
1044
  end
933
1045
  end
934
1046
  ruby2_keywords(:method_missing)
935
1047
 
936
1048
  def copy(destination, sources, options = {})
937
1049
  copied = []
938
- schema_migration = options[:schema_migration] || ActiveRecord::SchemaMigration
939
1050
 
940
1051
  FileUtils.mkdir_p(destination) unless File.exist?(destination)
1052
+ schema_migration = SchemaMigration::NullSchemaMigration.new
1053
+ internal_metadata = InternalMetadata::NullInternalMetadata.new
941
1054
 
942
- destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration).migrations
1055
+ destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration, internal_metadata).migrations
943
1056
  last = destination_migrations.last
944
1057
  sources.each do |scope, path|
945
- source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration).migrations
1058
+ source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration, internal_metadata).migrations
946
1059
 
947
1060
  source_migrations.each do |migration|
948
1061
  source = File.binread(migration.filename)
@@ -1001,9 +1114,9 @@ module ActiveRecord
1001
1114
  # Determines the version number of the next migration.
1002
1115
  def next_migration_number(number)
1003
1116
  if ActiveRecord.timestamped_migrations
1004
- [Time.now.utc.strftime("%Y%m%d%H%M%S").to_i, ("%.14d" % number).to_i].max
1117
+ [Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max
1005
1118
  else
1006
- SchemaMigration.normalize_migration_number(number)
1119
+ "%.3d" % number.to_i
1007
1120
  end
1008
1121
  end
1009
1122
 
@@ -1025,6 +1138,22 @@ module ActiveRecord
1025
1138
  end
1026
1139
  end
1027
1140
 
1141
+ def format_arguments(arguments)
1142
+ arg_list = arguments[0...-1].map(&:inspect)
1143
+ last_arg = arguments.last
1144
+ if last_arg.is_a?(Hash)
1145
+ last_arg = last_arg.reject { |k, _v| internal_option?(k) }
1146
+ arg_list << last_arg.inspect unless last_arg.empty?
1147
+ else
1148
+ arg_list << last_arg.inspect
1149
+ end
1150
+ arg_list.join(", ")
1151
+ end
1152
+
1153
+ def internal_option?(option_name)
1154
+ option_name.start_with?("_")
1155
+ end
1156
+
1028
1157
  def command_recorder
1029
1158
  CommandRecorder.new(connection)
1030
1159
  end
@@ -1057,19 +1186,44 @@ module ActiveRecord
1057
1186
  end
1058
1187
  end
1059
1188
 
1189
+ # = \Migration \Context
1190
+ #
1060
1191
  # MigrationContext sets the context in which a migration is run.
1061
1192
  #
1062
1193
  # A migration context requires the path to the migrations is set
1063
1194
  # 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.
1195
+ # class can be provided. Multiple database applications will instantiate
1196
+ # a +SchemaMigration+ object per database. From the Rake tasks, \Rails will
1197
+ # handle this for you.
1067
1198
  class MigrationContext
1068
- attr_reader :migrations_paths, :schema_migration
1199
+ attr_reader :migrations_paths, :schema_migration, :internal_metadata
1200
+
1201
+ def initialize(migrations_paths, schema_migration = nil, internal_metadata = nil)
1202
+ if schema_migration == SchemaMigration
1203
+ ActiveRecord.deprecator.warn(<<-MSG.squish)
1204
+ SchemaMigration no longer inherits from ActiveRecord::Base. If you want
1205
+ to use the default connection, remove this argument. If you want to use a
1206
+ specific connection, instantiate MigrationContext with the connection's schema
1207
+ migration, for example `MigrationContext.new(path, Dog.connection.schema_migration)`.
1208
+ MSG
1209
+
1210
+ schema_migration = nil
1211
+ end
1212
+
1213
+ if internal_metadata == InternalMetadata
1214
+ ActiveRecord.deprecator.warn(<<-MSG.squish)
1215
+ SchemaMigration no longer inherits from ActiveRecord::Base. If you want
1216
+ to use the default connection, remove this argument. If you want to use a
1217
+ specific connection, instantiate MigrationContext with the connection's internal
1218
+ metadata, for example `MigrationContext.new(path, nil, Dog.connection.internal_metadata)`.
1219
+ MSG
1220
+
1221
+ internal_metadata = nil
1222
+ end
1069
1223
 
1070
- def initialize(migrations_paths, schema_migration = SchemaMigration)
1071
1224
  @migrations_paths = migrations_paths
1072
- @schema_migration = schema_migration
1225
+ @schema_migration = schema_migration || SchemaMigration.new(connection)
1226
+ @internal_metadata = internal_metadata || InternalMetadata.new(connection)
1073
1227
  end
1074
1228
 
1075
1229
  # Runs the migrations in the +migrations_path+.
@@ -1113,7 +1267,7 @@ module ActiveRecord
1113
1267
  migrations
1114
1268
  end
1115
1269
 
1116
- Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate
1270
+ Migrator.new(:up, selected_migrations, schema_migration, internal_metadata, target_version).migrate
1117
1271
  end
1118
1272
 
1119
1273
  def down(target_version = nil, &block) # :nodoc:
@@ -1123,20 +1277,20 @@ module ActiveRecord
1123
1277
  migrations
1124
1278
  end
1125
1279
 
1126
- Migrator.new(:down, selected_migrations, schema_migration, target_version).migrate
1280
+ Migrator.new(:down, selected_migrations, schema_migration, internal_metadata, target_version).migrate
1127
1281
  end
1128
1282
 
1129
1283
  def run(direction, target_version) # :nodoc:
1130
- Migrator.new(direction, migrations, schema_migration, target_version).run
1284
+ Migrator.new(direction, migrations, schema_migration, internal_metadata, target_version).run
1131
1285
  end
1132
1286
 
1133
1287
  def open # :nodoc:
1134
- Migrator.new(:up, migrations, schema_migration)
1288
+ Migrator.new(:up, migrations, schema_migration, internal_metadata)
1135
1289
  end
1136
1290
 
1137
1291
  def get_all_versions # :nodoc:
1138
1292
  if schema_migration.table_exists?
1139
- schema_migration.all_versions.map(&:to_i)
1293
+ schema_migration.integer_versions
1140
1294
  else
1141
1295
  []
1142
1296
  end
@@ -1195,16 +1349,20 @@ module ActiveRecord
1195
1349
  end
1196
1350
 
1197
1351
  def last_stored_environment # :nodoc:
1198
- return nil unless ActiveRecord::InternalMetadata.enabled?
1352
+ return nil unless connection.internal_metadata.enabled?
1199
1353
  return nil if current_version == 0
1200
- raise NoEnvironmentInSchemaError unless ActiveRecord::InternalMetadata.table_exists?
1354
+ raise NoEnvironmentInSchemaError unless connection.internal_metadata.table_exists?
1201
1355
 
1202
- environment = ActiveRecord::InternalMetadata[:environment]
1356
+ environment = connection.internal_metadata[:environment]
1203
1357
  raise NoEnvironmentInSchemaError unless environment
1204
1358
  environment
1205
1359
  end
1206
1360
 
1207
1361
  private
1362
+ def connection
1363
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection
1364
+ end
1365
+
1208
1366
  def migration_files
1209
1367
  paths = Array(migrations_paths)
1210
1368
  Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
@@ -1215,7 +1373,7 @@ module ActiveRecord
1215
1373
  end
1216
1374
 
1217
1375
  def move(direction, steps)
1218
- migrator = Migrator.new(direction, migrations, schema_migration)
1376
+ migrator = Migrator.new(direction, migrations, schema_migration, internal_metadata)
1219
1377
 
1220
1378
  if current_version != 0 && !migrator.current_migration
1221
1379
  raise UnknownMigrationVersionError.new(current_version)
@@ -1240,23 +1398,28 @@ module ActiveRecord
1240
1398
 
1241
1399
  # For cases where a table doesn't exist like loading from schema cache
1242
1400
  def current_version
1243
- MigrationContext.new(migrations_paths, SchemaMigration).current_version
1401
+ connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection
1402
+ schema_migration = SchemaMigration.new(connection)
1403
+ internal_metadata = InternalMetadata.new(connection)
1404
+
1405
+ MigrationContext.new(migrations_paths, schema_migration, internal_metadata).current_version
1244
1406
  end
1245
1407
  end
1246
1408
 
1247
1409
  self.migrations_paths = ["db/migrate"]
1248
1410
 
1249
- def initialize(direction, migrations, schema_migration, target_version = nil)
1411
+ def initialize(direction, migrations, schema_migration, internal_metadata, target_version = nil)
1250
1412
  @direction = direction
1251
1413
  @target_version = target_version
1252
1414
  @migrated_versions = nil
1253
1415
  @migrations = migrations
1254
1416
  @schema_migration = schema_migration
1417
+ @internal_metadata = internal_metadata
1255
1418
 
1256
1419
  validate(@migrations)
1257
1420
 
1258
1421
  @schema_migration.create_table
1259
- ActiveRecord::InternalMetadata.create_table
1422
+ @internal_metadata.create_table
1260
1423
  end
1261
1424
 
1262
1425
  def current_version
@@ -1309,18 +1472,21 @@ module ActiveRecord
1309
1472
  end
1310
1473
 
1311
1474
  def load_migrated
1312
- @migrated_versions = Set.new(@schema_migration.all_versions.map(&:to_i))
1475
+ @migrated_versions = Set.new(@schema_migration.integer_versions)
1313
1476
  end
1314
1477
 
1315
1478
  private
1479
+ def connection
1480
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection
1481
+ end
1482
+
1316
1483
  # Used for running a specific migration.
1317
1484
  def run_without_lock
1318
1485
  migration = migrations.detect { |m| m.version == @target_version }
1319
1486
  raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
1320
- result = execute_migration_in_transaction(migration)
1321
1487
 
1322
1488
  record_environment
1323
- result
1489
+ execute_migration_in_transaction(migration)
1324
1490
  end
1325
1491
 
1326
1492
  # Used for running multiple migrations up to or down to a certain value.
@@ -1329,15 +1495,15 @@ module ActiveRecord
1329
1495
  raise UnknownMigrationVersionError.new(@target_version)
1330
1496
  end
1331
1497
 
1332
- result = runnable.each(&method(:execute_migration_in_transaction))
1333
1498
  record_environment
1334
- result
1499
+ runnable.each(&method(:execute_migration_in_transaction))
1335
1500
  end
1336
1501
 
1337
1502
  # Stores the current environment in the database.
1338
1503
  def record_environment
1339
1504
  return if down?
1340
- ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Base.connection.migration_context.current_environment
1505
+
1506
+ @internal_metadata[:environment] = connection.pool.db_config.env_name
1341
1507
  end
1342
1508
 
1343
1509
  def ran?(migration)
@@ -1389,10 +1555,10 @@ module ActiveRecord
1389
1555
  def record_version_state_after_migrating(version)
1390
1556
  if down?
1391
1557
  migrated.delete(version)
1392
- @schema_migration.delete_by(version: version.to_s)
1558
+ @schema_migration.delete_version(version.to_s)
1393
1559
  else
1394
1560
  migrated << version
1395
- @schema_migration.create!(version: version.to_s)
1561
+ @schema_migration.create_version(version.to_s)
1396
1562
  end
1397
1563
  end
1398
1564
 
@@ -1407,50 +1573,38 @@ module ActiveRecord
1407
1573
  # Wrap the migration in a transaction only if supported by the adapter.
1408
1574
  def ddl_transaction(migration, &block)
1409
1575
  if use_transaction?(migration)
1410
- Base.transaction(&block)
1576
+ connection.transaction(&block)
1411
1577
  else
1412
1578
  yield
1413
1579
  end
1414
1580
  end
1415
1581
 
1416
1582
  def use_transaction?(migration)
1417
- !migration.disable_ddl_transaction && Base.connection.supports_ddl_transactions?
1583
+ !migration.disable_ddl_transaction && connection.supports_ddl_transactions?
1418
1584
  end
1419
1585
 
1420
1586
  def use_advisory_lock?
1421
- Base.connection.advisory_locks_enabled?
1587
+ connection.advisory_locks_enabled?
1422
1588
  end
1423
1589
 
1424
1590
  def with_advisory_lock
1425
1591
  lock_id = generate_migrator_advisory_lock_id
1426
1592
 
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)
1593
+ got_lock = connection.get_advisory_lock(lock_id)
1594
+ raise ConcurrentMigrationError unless got_lock
1595
+ load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
1596
+ yield
1447
1597
  ensure
1448
- pool&.disconnect!
1598
+ if got_lock && !connection.release_advisory_lock(lock_id)
1599
+ raise ConcurrentMigrationError.new(
1600
+ ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
1601
+ )
1602
+ end
1449
1603
  end
1450
1604
 
1451
1605
  MIGRATOR_SALT = 2053462845
1452
1606
  def generate_migrator_advisory_lock_id
1453
- db_name_hash = Zlib.crc32(Base.connection.current_database)
1607
+ db_name_hash = Zlib.crc32(connection.current_database)
1454
1608
  MIGRATOR_SALT * db_name_hash
1455
1609
  end
1456
1610
  end