activerecord 7.0.10 → 7.1.0.beta1

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 (228) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1348 -1672
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +15 -17
  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 -9
  15. data/lib/active_record/associations/collection_proxy.rb +16 -11
  16. data/lib/active_record/associations/foreign_association.rb +10 -3
  17. data/lib/active_record/associations/has_many_association.rb +20 -13
  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 +10 -8
  21. data/lib/active_record/associations/preloader/association.rb +27 -6
  22. data/lib/active_record/associations/preloader.rb +12 -9
  23. data/lib/active_record/associations/singular_association.rb +1 -1
  24. data/lib/active_record/associations/through_association.rb +22 -11
  25. data/lib/active_record/associations.rb +313 -217
  26. data/lib/active_record/attribute_assignment.rb +0 -2
  27. data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
  28. data/lib/active_record/attribute_methods/dirty.rb +48 -38
  29. data/lib/active_record/attribute_methods/primary_key.rb +76 -24
  30. data/lib/active_record/attribute_methods/query.rb +28 -16
  31. data/lib/active_record/attribute_methods/read.rb +18 -5
  32. data/lib/active_record/attribute_methods/serialization.rb +150 -31
  33. data/lib/active_record/attribute_methods/write.rb +3 -3
  34. data/lib/active_record/attribute_methods.rb +105 -21
  35. data/lib/active_record/attributes.rb +3 -3
  36. data/lib/active_record/autosave_association.rb +55 -9
  37. data/lib/active_record/base.rb +7 -2
  38. data/lib/active_record/callbacks.rb +10 -24
  39. data/lib/active_record/coders/column_serializer.rb +61 -0
  40. data/lib/active_record/coders/json.rb +1 -1
  41. data/lib/active_record/coders/yaml_column.rb +70 -42
  42. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +163 -88
  43. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
  44. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +3 -1
  45. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +65 -49
  46. data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
  47. data/lib/active_record/connection_adapters/abstract/database_statements.rb +109 -32
  48. data/lib/active_record/connection_adapters/abstract/query_cache.rb +60 -22
  49. data/lib/active_record/connection_adapters/abstract/quoting.rb +41 -6
  50. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  51. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
  52. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +137 -11
  53. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +291 -122
  54. data/lib/active_record/connection_adapters/abstract/transaction.rb +280 -58
  55. data/lib/active_record/connection_adapters/abstract_adapter.rb +502 -91
  56. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +200 -115
  57. data/lib/active_record/connection_adapters/column.rb +9 -0
  58. data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
  59. data/lib/active_record/connection_adapters/mysql/database_statements.rb +22 -143
  60. data/lib/active_record/connection_adapters/mysql/quoting.rb +16 -12
  61. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
  62. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +6 -0
  63. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
  64. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +18 -14
  65. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +148 -0
  66. data/lib/active_record/connection_adapters/mysql2_adapter.rb +98 -53
  67. data/lib/active_record/connection_adapters/pool_config.rb +14 -5
  68. data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
  69. data/lib/active_record/connection_adapters/postgresql/column.rb +1 -2
  70. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +76 -29
  71. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -3
  72. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
  73. data/lib/active_record/connection_adapters/postgresql/quoting.rb +9 -6
  74. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +3 -9
  75. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
  76. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +131 -2
  77. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +42 -0
  78. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +352 -55
  79. data/lib/active_record/connection_adapters/postgresql_adapter.rb +336 -168
  80. data/lib/active_record/connection_adapters/schema_cache.rb +287 -59
  81. data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
  82. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +42 -36
  83. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +4 -3
  84. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +1 -0
  85. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +26 -7
  86. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +162 -77
  87. data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
  88. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +98 -0
  89. data/lib/active_record/connection_adapters/trilogy_adapter.rb +254 -0
  90. data/lib/active_record/connection_adapters.rb +3 -1
  91. data/lib/active_record/connection_handling.rb +72 -95
  92. data/lib/active_record/core.rb +131 -142
  93. data/lib/active_record/counter_cache.rb +46 -25
  94. data/lib/active_record/database_configurations/database_config.rb +9 -3
  95. data/lib/active_record/database_configurations/hash_config.rb +22 -12
  96. data/lib/active_record/database_configurations/url_config.rb +17 -11
  97. data/lib/active_record/database_configurations.rb +86 -33
  98. data/lib/active_record/delegated_type.rb +11 -6
  99. data/lib/active_record/deprecator.rb +7 -0
  100. data/lib/active_record/destroy_association_async_job.rb +2 -0
  101. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  102. data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
  103. data/lib/active_record/encryption/config.rb +25 -1
  104. data/lib/active_record/encryption/configurable.rb +12 -19
  105. data/lib/active_record/encryption/context.rb +10 -3
  106. data/lib/active_record/encryption/contexts.rb +5 -1
  107. data/lib/active_record/encryption/derived_secret_key_provider.rb +8 -2
  108. data/lib/active_record/encryption/encryptable_record.rb +36 -18
  109. data/lib/active_record/encryption/encrypted_attribute_type.rb +17 -6
  110. data/lib/active_record/encryption/extended_deterministic_queries.rb +52 -12
  111. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +2 -2
  112. data/lib/active_record/encryption/key_generator.rb +12 -1
  113. data/lib/active_record/encryption/message_serializer.rb +2 -0
  114. data/lib/active_record/encryption/properties.rb +3 -3
  115. data/lib/active_record/encryption/scheme.rb +19 -22
  116. data/lib/active_record/encryption.rb +1 -0
  117. data/lib/active_record/enum.rb +113 -26
  118. data/lib/active_record/errors.rb +89 -15
  119. data/lib/active_record/explain.rb +23 -3
  120. data/lib/active_record/fixture_set/model_metadata.rb +14 -4
  121. data/lib/active_record/fixture_set/render_context.rb +2 -0
  122. data/lib/active_record/fixture_set/table_row.rb +29 -8
  123. data/lib/active_record/fixtures.rb +119 -83
  124. data/lib/active_record/future_result.rb +30 -5
  125. data/lib/active_record/gem_version.rb +4 -4
  126. data/lib/active_record/inheritance.rb +30 -16
  127. data/lib/active_record/insert_all.rb +58 -11
  128. data/lib/active_record/integration.rb +8 -8
  129. data/lib/active_record/internal_metadata.rb +118 -30
  130. data/lib/active_record/locking/pessimistic.rb +5 -2
  131. data/lib/active_record/log_subscriber.rb +29 -12
  132. data/lib/active_record/marshalling.rb +56 -0
  133. data/lib/active_record/message_pack.rb +124 -0
  134. data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
  135. data/lib/active_record/middleware/database_selector.rb +6 -8
  136. data/lib/active_record/middleware/shard_selector.rb +3 -1
  137. data/lib/active_record/migration/command_recorder.rb +100 -4
  138. data/lib/active_record/migration/compatibility.rb +131 -5
  139. data/lib/active_record/migration/default_strategy.rb +23 -0
  140. data/lib/active_record/migration/execution_strategy.rb +19 -0
  141. data/lib/active_record/migration.rb +215 -112
  142. data/lib/active_record/model_schema.rb +50 -32
  143. data/lib/active_record/nested_attributes.rb +31 -6
  144. data/lib/active_record/normalization.rb +158 -0
  145. data/lib/active_record/persistence.rb +183 -33
  146. data/lib/active_record/promise.rb +84 -0
  147. data/lib/active_record/query_cache.rb +3 -21
  148. data/lib/active_record/query_logs.rb +77 -52
  149. data/lib/active_record/query_logs_formatter.rb +41 -0
  150. data/lib/active_record/querying.rb +15 -2
  151. data/lib/active_record/railtie.rb +108 -46
  152. data/lib/active_record/railties/controller_runtime.rb +10 -5
  153. data/lib/active_record/railties/databases.rake +139 -145
  154. data/lib/active_record/railties/job_runtime.rb +23 -0
  155. data/lib/active_record/readonly_attributes.rb +32 -5
  156. data/lib/active_record/reflection.rb +169 -45
  157. data/lib/active_record/relation/batches/batch_enumerator.rb +5 -3
  158. data/lib/active_record/relation/batches.rb +190 -61
  159. data/lib/active_record/relation/calculations.rb +152 -63
  160. data/lib/active_record/relation/delegation.rb +23 -9
  161. data/lib/active_record/relation/finder_methods.rb +85 -15
  162. data/lib/active_record/relation/merger.rb +2 -0
  163. data/lib/active_record/relation/predicate_builder/association_query_value.rb +11 -2
  164. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  165. data/lib/active_record/relation/predicate_builder.rb +26 -14
  166. data/lib/active_record/relation/query_attribute.rb +2 -1
  167. data/lib/active_record/relation/query_methods.rb +351 -62
  168. data/lib/active_record/relation/spawn_methods.rb +18 -1
  169. data/lib/active_record/relation.rb +75 -34
  170. data/lib/active_record/result.rb +19 -5
  171. data/lib/active_record/runtime_registry.rb +10 -1
  172. data/lib/active_record/sanitization.rb +51 -11
  173. data/lib/active_record/schema.rb +2 -3
  174. data/lib/active_record/schema_dumper.rb +41 -7
  175. data/lib/active_record/schema_migration.rb +68 -33
  176. data/lib/active_record/scoping/default.rb +15 -5
  177. data/lib/active_record/scoping/named.rb +2 -2
  178. data/lib/active_record/scoping.rb +2 -1
  179. data/lib/active_record/secure_password.rb +60 -0
  180. data/lib/active_record/secure_token.rb +21 -3
  181. data/lib/active_record/signed_id.rb +7 -5
  182. data/lib/active_record/store.rb +8 -8
  183. data/lib/active_record/suppressor.rb +3 -1
  184. data/lib/active_record/table_metadata.rb +10 -1
  185. data/lib/active_record/tasks/database_tasks.rb +127 -105
  186. data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
  187. data/lib/active_record/tasks/postgresql_database_tasks.rb +16 -13
  188. data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -7
  189. data/lib/active_record/test_fixtures.rb +113 -96
  190. data/lib/active_record/timestamp.rb +27 -15
  191. data/lib/active_record/token_for.rb +113 -0
  192. data/lib/active_record/touch_later.rb +11 -6
  193. data/lib/active_record/transactions.rb +36 -10
  194. data/lib/active_record/type/adapter_specific_registry.rb +1 -8
  195. data/lib/active_record/type/internal/timezone.rb +7 -2
  196. data/lib/active_record/type/time.rb +4 -0
  197. data/lib/active_record/validations/absence.rb +1 -1
  198. data/lib/active_record/validations/numericality.rb +5 -4
  199. data/lib/active_record/validations/presence.rb +5 -28
  200. data/lib/active_record/validations/uniqueness.rb +47 -2
  201. data/lib/active_record/validations.rb +8 -4
  202. data/lib/active_record/version.rb +1 -1
  203. data/lib/active_record.rb +121 -16
  204. data/lib/arel/errors.rb +10 -0
  205. data/lib/arel/factory_methods.rb +4 -0
  206. data/lib/arel/nodes/binary.rb +6 -1
  207. data/lib/arel/nodes/bound_sql_literal.rb +61 -0
  208. data/lib/arel/nodes/cte.rb +36 -0
  209. data/lib/arel/nodes/fragments.rb +35 -0
  210. data/lib/arel/nodes/homogeneous_in.rb +1 -9
  211. data/lib/arel/nodes/leading_join.rb +8 -0
  212. data/lib/arel/nodes/node.rb +111 -2
  213. data/lib/arel/nodes/sql_literal.rb +6 -0
  214. data/lib/arel/nodes/table_alias.rb +4 -0
  215. data/lib/arel/nodes.rb +4 -0
  216. data/lib/arel/predications.rb +2 -0
  217. data/lib/arel/table.rb +9 -5
  218. data/lib/arel/visitors/mysql.rb +8 -1
  219. data/lib/arel/visitors/to_sql.rb +81 -17
  220. data/lib/arel/visitors/visitor.rb +2 -2
  221. data/lib/arel.rb +16 -2
  222. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  223. data/lib/rails/generators/active_record/migration.rb +3 -1
  224. data/lib/rails/generators/active_record/model/USAGE +113 -0
  225. data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
  226. metadata +52 -14
  227. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
  228. 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
@@ -356,16 +362,15 @@ 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
- #
368
- # $ bin/rails generate migration MyNewMigration
373
+ # bin/rails generate migration MyNewMigration
369
374
  #
370
375
  # where MyNewMigration is the name of your migration. The generator will
371
376
  # create an empty migration file <tt>timestamp_my_new_migration.rb</tt>
@@ -374,10 +379,10 @@ module ActiveRecord
374
379
  #
375
380
  # There is a special syntactic shortcut to generate migrations that add fields to a table.
376
381
  #
377
- # $ bin/rails generate migration add_fieldname_to_tablename fieldname:string
382
+ # bin/rails generate migration add_fieldname_to_tablename fieldname:string
378
383
  #
379
384
  # This will generate the file <tt>timestamp_add_fieldname_to_tablename.rb</tt>, which will look like this:
380
- # class AddFieldnameToTablename < ActiveRecord::Migration[7.0]
385
+ # class AddFieldnameToTablename < ActiveRecord::Migration[7.1]
381
386
  # def change
382
387
  # add_column :tablenames, :fieldname, :string
383
388
  # end
@@ -396,14 +401,14 @@ module ActiveRecord
396
401
  # wish to rollback last few migrations. <tt>bin/rails db:rollback STEP=2</tt> will rollback
397
402
  # the latest two migrations.
398
403
  #
399
- # If any of the migrations throw an <tt>ActiveRecord::IrreversibleMigration</tt> exception,
404
+ # If any of the migrations throw an ActiveRecord::IrreversibleMigration exception,
400
405
  # that step will fail and you'll have some manual work to do.
401
406
  #
402
407
  # == More examples
403
408
  #
404
409
  # Not all migrations change the schema. Some just fix the data:
405
410
  #
406
- # class RemoveEmptyTags < ActiveRecord::Migration[7.0]
411
+ # class RemoveEmptyTags < ActiveRecord::Migration[7.1]
407
412
  # def up
408
413
  # Tag.all.each { |tag| tag.destroy if tag.pages.empty? }
409
414
  # end
@@ -416,7 +421,7 @@ module ActiveRecord
416
421
  #
417
422
  # Others remove columns when they migrate up instead of down:
418
423
  #
419
- # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[7.0]
424
+ # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[7.1]
420
425
  # def up
421
426
  # remove_column :items, :incomplete_items_count
422
427
  # remove_column :items, :completed_items_count
@@ -430,7 +435,7 @@ module ActiveRecord
430
435
  #
431
436
  # And sometimes you need to do something in SQL not abstracted directly by migrations:
432
437
  #
433
- # class MakeJoinUnique < ActiveRecord::Migration[7.0]
438
+ # class MakeJoinUnique < ActiveRecord::Migration[7.1]
434
439
  # def up
435
440
  # execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)"
436
441
  # end
@@ -447,7 +452,7 @@ module ActiveRecord
447
452
  # <tt>Base#reset_column_information</tt> in order to ensure that the model has the
448
453
  # latest column data from after the new column was added. Example:
449
454
  #
450
- # class AddPeopleSalary < ActiveRecord::Migration[7.0]
455
+ # class AddPeopleSalary < ActiveRecord::Migration[7.1]
451
456
  # def up
452
457
  # add_column :people, :salary, :integer
453
458
  # Person.reset_column_information
@@ -483,7 +488,7 @@ module ActiveRecord
483
488
  #
484
489
  # == Timestamped Migrations
485
490
  #
486
- # By default, Rails generates migrations that look like:
491
+ # By default, \Rails generates migrations that look like:
487
492
  #
488
493
  # 20080717013526_your_migration_name.rb
489
494
  #
@@ -505,7 +510,7 @@ module ActiveRecord
505
510
  # To define a reversible migration, define the +change+ method in your
506
511
  # migration like this:
507
512
  #
508
- # class TenderloveMigration < ActiveRecord::Migration[7.0]
513
+ # class TenderloveMigration < ActiveRecord::Migration[7.1]
509
514
  # def change
510
515
  # create_table(:horses) do |t|
511
516
  # t.column :content, :text
@@ -522,11 +527,11 @@ module ActiveRecord
522
527
  # as before.
523
528
  #
524
529
  # If a command cannot be reversed, an
525
- # <tt>ActiveRecord::IrreversibleMigration</tt> exception will be raised when
530
+ # ActiveRecord::IrreversibleMigration exception will be raised when
526
531
  # the migration is moving down.
527
532
  #
528
533
  # For a list of commands that are reversible, please see
529
- # <tt>ActiveRecord::Migration::CommandRecorder</tt>.
534
+ # +ActiveRecord::Migration::CommandRecorder+.
530
535
  #
531
536
  # == Transactional Migrations
532
537
  #
@@ -535,7 +540,7 @@ module ActiveRecord
535
540
  # can't execute inside a transaction though, and for these situations
536
541
  # you can turn the automatic transactions off.
537
542
  #
538
- # class ChangeEnum < ActiveRecord::Migration[7.0]
543
+ # class ChangeEnum < ActiveRecord::Migration[7.1]
539
544
  # disable_ddl_transaction!
540
545
  #
541
546
  # def up
@@ -549,6 +554,8 @@ module ActiveRecord
549
554
  autoload :CommandRecorder, "active_record/migration/command_recorder"
550
555
  autoload :Compatibility, "active_record/migration/compatibility"
551
556
  autoload :JoinTable, "active_record/migration/join_table"
557
+ autoload :ExecutionStrategy, "active_record/migration/execution_strategy"
558
+ autoload :DefaultStrategy, "active_record/migration/default_strategy"
552
559
 
553
560
  # This must be defined before the inherited hook, below
554
561
  class Current < Migration # :nodoc:
@@ -611,6 +618,13 @@ module ActiveRecord
611
618
 
612
619
  MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/ # :nodoc:
613
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
+
614
628
  # This class is used to verify that all migrations have been run before
615
629
  # loading a web page if <tt>config.active_record.migration_error</tt> is set to +:page_load+.
616
630
  class CheckPending
@@ -625,7 +639,7 @@ module ActiveRecord
625
639
  @mutex.synchronize do
626
640
  @watcher ||= build_watcher do
627
641
  @needs_check = true
628
- ActiveRecord::Migration.check_pending!(connection)
642
+ ActiveRecord::Migration.check_pending_migrations
629
643
  @needs_check = false
630
644
  end
631
645
 
@@ -641,12 +655,14 @@ module ActiveRecord
641
655
 
642
656
  private
643
657
  def build_watcher(&block)
644
- 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
645
661
  @file_watcher.new([], paths.index_with(["rb"]), &block)
646
662
  end
647
663
 
648
664
  def connection
649
- ActiveRecord::Base.connection
665
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection
650
666
  end
651
667
  end
652
668
 
@@ -658,32 +674,53 @@ module ActiveRecord
658
674
  delegate || superclass.nearest_delegate
659
675
  end
660
676
 
661
- # Raises <tt>ActiveRecord::PendingMigrationError</tt> error if any migrations are pending.
662
- def check_pending!(connection = Base.connection)
663
- 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
664
692
  end
665
693
 
666
- def load_schema_if_pending!
667
- current_db_config = Base.connection_db_config
668
- 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 = []
698
+
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
703
+ end
669
704
 
670
- needs_update = !all_configs.all? do |db_config|
671
- Tasks::DatabaseTasks.schema_up_to_date?(db_config, ActiveRecord.schema_format)
705
+ migrations = pending_migrations.flatten
706
+
707
+ if migrations.any?
708
+ raise ActiveRecord::PendingMigrationError.new(pending_migrations: migrations)
672
709
  end
710
+ end
673
711
 
674
- if needs_update
712
+ def load_schema_if_pending!
713
+ if any_schema_needs_update?
675
714
  # Roundtrip to Rake to allow plugins to hook into database initialization.
676
715
  root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
716
+
677
717
  FileUtils.cd(root) do
678
- Base.clear_all_connections!
718
+ Base.connection_handler.clear_all_connections!(:all)
679
719
  system("bin/rails db:test:prepare")
680
720
  end
681
721
  end
682
722
 
683
- # Establish a new connection, the old database may be gone (db:test:prepare uses purge)
684
- Base.establish_connection(current_db_config)
685
-
686
- check_pending!
723
+ check_pending_migrations
687
724
  end
688
725
 
689
726
  def maintain_test_schema! # :nodoc:
@@ -708,6 +745,41 @@ module ActiveRecord
708
745
  def disable_ddl_transaction!
709
746
  @disable_ddl_transaction = true
710
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
711
783
  end
712
784
 
713
785
  def disable_ddl_transaction # :nodoc:
@@ -723,6 +795,10 @@ module ActiveRecord
723
795
  @connection = nil
724
796
  end
725
797
 
798
+ def execution_strategy
799
+ @execution_strategy ||= ActiveRecord.migration_strategy.new(self)
800
+ end
801
+
726
802
  self.verbose = true
727
803
  # instantiate the delegate object after initialize is defined
728
804
  self.delegate = new
@@ -734,7 +810,7 @@ module ActiveRecord
734
810
  # and create the table 'apples' on the way up, and the reverse
735
811
  # on the way down.
736
812
  #
737
- # class FixTLMigration < ActiveRecord::Migration[7.0]
813
+ # class FixTLMigration < ActiveRecord::Migration[7.1]
738
814
  # def change
739
815
  # revert do
740
816
  # create_table(:horses) do |t|
@@ -753,7 +829,7 @@ module ActiveRecord
753
829
  #
754
830
  # require_relative "20121212123456_tenderlove_migration"
755
831
  #
756
- # class FixupTLMigration < ActiveRecord::Migration[7.0]
832
+ # class FixupTLMigration < ActiveRecord::Migration[7.1]
757
833
  # def change
758
834
  # revert TenderloveMigration
759
835
  #
@@ -804,7 +880,7 @@ module ActiveRecord
804
880
  # when the three columns 'first_name', 'last_name' and 'full_name' exist,
805
881
  # even when migrating down:
806
882
  #
807
- # class SplitNameMigration < ActiveRecord::Migration[7.0]
883
+ # class SplitNameMigration < ActiveRecord::Migration[7.1]
808
884
  # def change
809
885
  # add_column :users, :first_name, :string
810
886
  # add_column :users, :last_name, :string
@@ -832,7 +908,7 @@ module ActiveRecord
832
908
  # In the following example, the new column +published+ will be given
833
909
  # the value +true+ for all existing records.
834
910
  #
835
- # class AddPublishedToPosts < ActiveRecord::Migration[7.0]
911
+ # class AddPublishedToPosts < ActiveRecord::Migration[7.1]
836
912
  # def change
837
913
  # add_column :posts, :published, :boolean, default: false
838
914
  # up_only do
@@ -885,7 +961,7 @@ module ActiveRecord
885
961
  end
886
962
 
887
963
  time = nil
888
- ActiveRecord::Base.connection_pool.with_connection do |conn|
964
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection.pool.with_connection do |conn|
889
965
  time = Benchmark.measure do
890
966
  exec_migration(conn, direction)
891
967
  end
@@ -910,6 +986,7 @@ module ActiveRecord
910
986
  end
911
987
  ensure
912
988
  @connection = nil
989
+ @execution_strategy = nil
913
990
  end
914
991
 
915
992
  def write(text = "")
@@ -948,7 +1025,7 @@ module ActiveRecord
948
1025
  end
949
1026
 
950
1027
  def connection
951
- @connection || ActiveRecord::Base.connection
1028
+ @connection || ActiveRecord::Tasks::DatabaseTasks.migration_connection
952
1029
  end
953
1030
 
954
1031
  def method_missing(method, *arguments, &block)
@@ -962,22 +1039,23 @@ module ActiveRecord
962
1039
  end
963
1040
  end
964
1041
  end
965
- return super unless connection.respond_to?(method)
966
- connection.send(method, *arguments, &block)
1042
+ return super unless execution_strategy.respond_to?(method)
1043
+ execution_strategy.send(method, *arguments, &block)
967
1044
  end
968
1045
  end
969
1046
  ruby2_keywords(:method_missing)
970
1047
 
971
1048
  def copy(destination, sources, options = {})
972
1049
  copied = []
973
- schema_migration = options[:schema_migration] || ActiveRecord::SchemaMigration
974
1050
 
975
1051
  FileUtils.mkdir_p(destination) unless File.exist?(destination)
1052
+ schema_migration = SchemaMigration::NullSchemaMigration.new
1053
+ internal_metadata = InternalMetadata::NullInternalMetadata.new
976
1054
 
977
- destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration).migrations
1055
+ destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration, internal_metadata).migrations
978
1056
  last = destination_migrations.last
979
1057
  sources.each do |scope, path|
980
- source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration).migrations
1058
+ source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration, internal_metadata).migrations
981
1059
 
982
1060
  source_migrations.each do |migration|
983
1061
  source = File.binread(migration.filename)
@@ -1038,7 +1116,7 @@ module ActiveRecord
1038
1116
  if ActiveRecord.timestamped_migrations
1039
1117
  [Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max
1040
1118
  else
1041
- SchemaMigration.normalize_migration_number(number)
1119
+ "%.3d" % number.to_i
1042
1120
  end
1043
1121
  end
1044
1122
 
@@ -1108,19 +1186,44 @@ module ActiveRecord
1108
1186
  end
1109
1187
  end
1110
1188
 
1189
+ # = \Migration \Context
1190
+ #
1111
1191
  # MigrationContext sets the context in which a migration is run.
1112
1192
  #
1113
1193
  # A migration context requires the path to the migrations is set
1114
1194
  # in the +migrations_paths+ parameter. Optionally a +schema_migration+
1115
- # class can be provided. For most applications, +SchemaMigration+ is
1116
- # sufficient. Multiple database applications need a +SchemaMigration+
1117
- # 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.
1118
1198
  class MigrationContext
1119
- 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
1120
1223
 
1121
- def initialize(migrations_paths, schema_migration = SchemaMigration)
1122
1224
  @migrations_paths = migrations_paths
1123
- @schema_migration = schema_migration
1225
+ @schema_migration = schema_migration || SchemaMigration.new(connection)
1226
+ @internal_metadata = internal_metadata || InternalMetadata.new(connection)
1124
1227
  end
1125
1228
 
1126
1229
  # Runs the migrations in the +migrations_path+.
@@ -1164,7 +1267,7 @@ module ActiveRecord
1164
1267
  migrations
1165
1268
  end
1166
1269
 
1167
- Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate
1270
+ Migrator.new(:up, selected_migrations, schema_migration, internal_metadata, target_version).migrate
1168
1271
  end
1169
1272
 
1170
1273
  def down(target_version = nil, &block) # :nodoc:
@@ -1174,20 +1277,20 @@ module ActiveRecord
1174
1277
  migrations
1175
1278
  end
1176
1279
 
1177
- Migrator.new(:down, selected_migrations, schema_migration, target_version).migrate
1280
+ Migrator.new(:down, selected_migrations, schema_migration, internal_metadata, target_version).migrate
1178
1281
  end
1179
1282
 
1180
1283
  def run(direction, target_version) # :nodoc:
1181
- Migrator.new(direction, migrations, schema_migration, target_version).run
1284
+ Migrator.new(direction, migrations, schema_migration, internal_metadata, target_version).run
1182
1285
  end
1183
1286
 
1184
1287
  def open # :nodoc:
1185
- Migrator.new(:up, migrations, schema_migration)
1288
+ Migrator.new(:up, migrations, schema_migration, internal_metadata)
1186
1289
  end
1187
1290
 
1188
1291
  def get_all_versions # :nodoc:
1189
1292
  if schema_migration.table_exists?
1190
- schema_migration.all_versions.map(&:to_i)
1293
+ schema_migration.integer_versions
1191
1294
  else
1192
1295
  []
1193
1296
  end
@@ -1246,16 +1349,20 @@ module ActiveRecord
1246
1349
  end
1247
1350
 
1248
1351
  def last_stored_environment # :nodoc:
1249
- return nil unless ActiveRecord::InternalMetadata.enabled?
1352
+ return nil unless connection.internal_metadata.enabled?
1250
1353
  return nil if current_version == 0
1251
- raise NoEnvironmentInSchemaError unless ActiveRecord::InternalMetadata.table_exists?
1354
+ raise NoEnvironmentInSchemaError unless connection.internal_metadata.table_exists?
1252
1355
 
1253
- environment = ActiveRecord::InternalMetadata[:environment]
1356
+ environment = connection.internal_metadata[:environment]
1254
1357
  raise NoEnvironmentInSchemaError unless environment
1255
1358
  environment
1256
1359
  end
1257
1360
 
1258
1361
  private
1362
+ def connection
1363
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection
1364
+ end
1365
+
1259
1366
  def migration_files
1260
1367
  paths = Array(migrations_paths)
1261
1368
  Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
@@ -1266,7 +1373,7 @@ module ActiveRecord
1266
1373
  end
1267
1374
 
1268
1375
  def move(direction, steps)
1269
- migrator = Migrator.new(direction, migrations, schema_migration)
1376
+ migrator = Migrator.new(direction, migrations, schema_migration, internal_metadata)
1270
1377
 
1271
1378
  if current_version != 0 && !migrator.current_migration
1272
1379
  raise UnknownMigrationVersionError.new(current_version)
@@ -1291,23 +1398,28 @@ module ActiveRecord
1291
1398
 
1292
1399
  # For cases where a table doesn't exist like loading from schema cache
1293
1400
  def current_version
1294
- 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
1295
1406
  end
1296
1407
  end
1297
1408
 
1298
1409
  self.migrations_paths = ["db/migrate"]
1299
1410
 
1300
- def initialize(direction, migrations, schema_migration, target_version = nil)
1411
+ def initialize(direction, migrations, schema_migration, internal_metadata, target_version = nil)
1301
1412
  @direction = direction
1302
1413
  @target_version = target_version
1303
1414
  @migrated_versions = nil
1304
1415
  @migrations = migrations
1305
1416
  @schema_migration = schema_migration
1417
+ @internal_metadata = internal_metadata
1306
1418
 
1307
1419
  validate(@migrations)
1308
1420
 
1309
1421
  @schema_migration.create_table
1310
- ActiveRecord::InternalMetadata.create_table
1422
+ @internal_metadata.create_table
1311
1423
  end
1312
1424
 
1313
1425
  def current_version
@@ -1360,18 +1472,21 @@ module ActiveRecord
1360
1472
  end
1361
1473
 
1362
1474
  def load_migrated
1363
- @migrated_versions = Set.new(@schema_migration.all_versions.map(&:to_i))
1475
+ @migrated_versions = Set.new(@schema_migration.integer_versions)
1364
1476
  end
1365
1477
 
1366
1478
  private
1479
+ def connection
1480
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection
1481
+ end
1482
+
1367
1483
  # Used for running a specific migration.
1368
1484
  def run_without_lock
1369
1485
  migration = migrations.detect { |m| m.version == @target_version }
1370
1486
  raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
1371
- result = execute_migration_in_transaction(migration)
1372
1487
 
1373
1488
  record_environment
1374
- result
1489
+ execute_migration_in_transaction(migration)
1375
1490
  end
1376
1491
 
1377
1492
  # Used for running multiple migrations up to or down to a certain value.
@@ -1380,15 +1495,15 @@ module ActiveRecord
1380
1495
  raise UnknownMigrationVersionError.new(@target_version)
1381
1496
  end
1382
1497
 
1383
- result = runnable.each(&method(:execute_migration_in_transaction))
1384
1498
  record_environment
1385
- result
1499
+ runnable.each(&method(:execute_migration_in_transaction))
1386
1500
  end
1387
1501
 
1388
1502
  # Stores the current environment in the database.
1389
1503
  def record_environment
1390
1504
  return if down?
1391
- ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Base.connection.pool.db_config.env_name
1505
+
1506
+ @internal_metadata[:environment] = connection.pool.db_config.env_name
1392
1507
  end
1393
1508
 
1394
1509
  def ran?(migration)
@@ -1440,10 +1555,10 @@ module ActiveRecord
1440
1555
  def record_version_state_after_migrating(version)
1441
1556
  if down?
1442
1557
  migrated.delete(version)
1443
- @schema_migration.delete_by(version: version.to_s)
1558
+ @schema_migration.delete_version(version.to_s)
1444
1559
  else
1445
1560
  migrated << version
1446
- @schema_migration.create!(version: version.to_s)
1561
+ @schema_migration.create_version(version.to_s)
1447
1562
  end
1448
1563
  end
1449
1564
 
@@ -1458,50 +1573,38 @@ module ActiveRecord
1458
1573
  # Wrap the migration in a transaction only if supported by the adapter.
1459
1574
  def ddl_transaction(migration, &block)
1460
1575
  if use_transaction?(migration)
1461
- Base.transaction(&block)
1576
+ connection.transaction(&block)
1462
1577
  else
1463
1578
  yield
1464
1579
  end
1465
1580
  end
1466
1581
 
1467
1582
  def use_transaction?(migration)
1468
- !migration.disable_ddl_transaction && Base.connection.supports_ddl_transactions?
1583
+ !migration.disable_ddl_transaction && connection.supports_ddl_transactions?
1469
1584
  end
1470
1585
 
1471
1586
  def use_advisory_lock?
1472
- Base.connection.advisory_locks_enabled?
1587
+ connection.advisory_locks_enabled?
1473
1588
  end
1474
1589
 
1475
1590
  def with_advisory_lock
1476
1591
  lock_id = generate_migrator_advisory_lock_id
1477
1592
 
1478
- with_advisory_lock_connection do |connection|
1479
- got_lock = connection.get_advisory_lock(lock_id)
1480
- raise ConcurrentMigrationError unless got_lock
1481
- load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
1482
- yield
1483
- ensure
1484
- if got_lock && !connection.release_advisory_lock(lock_id)
1485
- raise ConcurrentMigrationError.new(
1486
- ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
1487
- )
1488
- end
1489
- end
1490
- end
1491
-
1492
- def with_advisory_lock_connection(&block)
1493
- pool = ActiveRecord::ConnectionAdapters::ConnectionHandler.new.establish_connection(
1494
- ActiveRecord::Base.connection_db_config
1495
- )
1496
-
1497
- 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
1498
1597
  ensure
1499
- 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
1500
1603
  end
1501
1604
 
1502
1605
  MIGRATOR_SALT = 2053462845
1503
1606
  def generate_migrator_advisory_lock_id
1504
- db_name_hash = Zlib.crc32(Base.connection.current_database)
1607
+ db_name_hash = Zlib.crc32(connection.current_database)
1505
1608
  MIGRATOR_SALT * db_name_hash
1506
1609
  end
1507
1610
  end