activerecord 7.0.6 → 7.1.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1424 -1390
- data/MIT-LICENSE +1 -1
- data/README.rdoc +15 -16
- data/lib/active_record/aggregations.rb +16 -13
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/association.rb +18 -3
- data/lib/active_record/associations/association_scope.rb +16 -9
- data/lib/active_record/associations/belongs_to_association.rb +14 -6
- data/lib/active_record/associations/builder/association.rb +3 -3
- data/lib/active_record/associations/builder/belongs_to.rb +21 -8
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +16 -10
- data/lib/active_record/associations/collection_proxy.rb +20 -10
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +20 -13
- data/lib/active_record/associations/has_many_through_association.rb +10 -6
- data/lib/active_record/associations/has_one_association.rb +10 -7
- data/lib/active_record/associations/join_dependency.rb +10 -8
- data/lib/active_record/associations/preloader/association.rb +27 -6
- data/lib/active_record/associations/preloader.rb +13 -10
- data/lib/active_record/associations/singular_association.rb +6 -8
- data/lib/active_record/associations/through_association.rb +22 -11
- data/lib/active_record/associations.rb +295 -199
- data/lib/active_record/attribute_assignment.rb +0 -2
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
- data/lib/active_record/attribute_methods/dirty.rb +40 -26
- data/lib/active_record/attribute_methods/primary_key.rb +76 -24
- data/lib/active_record/attribute_methods/query.rb +28 -16
- data/lib/active_record/attribute_methods/read.rb +18 -5
- data/lib/active_record/attribute_methods/serialization.rb +150 -31
- data/lib/active_record/attribute_methods/write.rb +3 -3
- data/lib/active_record/attribute_methods.rb +105 -21
- data/lib/active_record/attributes.rb +3 -3
- data/lib/active_record/autosave_association.rb +60 -18
- data/lib/active_record/base.rb +7 -2
- data/lib/active_record/callbacks.rb +10 -24
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -42
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +163 -88
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +3 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +63 -43
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +128 -32
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +60 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +41 -6
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +137 -11
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +289 -124
- data/lib/active_record/connection_adapters/abstract/transaction.rb +287 -58
- data/lib/active_record/connection_adapters/abstract_adapter.rb +496 -102
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +214 -113
- data/lib/active_record/connection_adapters/column.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +23 -144
- data/lib/active_record/connection_adapters/mysql/quoting.rb +21 -14
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +6 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +18 -13
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +148 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +98 -53
- data/lib/active_record/connection_adapters/pool_config.rb +14 -5
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +14 -3
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +71 -40
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +15 -8
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +3 -9
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +131 -2
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +53 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +349 -55
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +338 -176
- data/lib/active_record/connection_adapters/schema_cache.rb +287 -59
- data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +45 -39
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +9 -5
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +28 -9
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +210 -83
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +98 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +254 -0
- data/lib/active_record/connection_adapters.rb +3 -1
- data/lib/active_record/connection_handling.rb +71 -94
- data/lib/active_record/core.rb +136 -148
- data/lib/active_record/counter_cache.rb +46 -25
- data/lib/active_record/database_configurations/database_config.rb +9 -3
- data/lib/active_record/database_configurations/hash_config.rb +22 -12
- data/lib/active_record/database_configurations/url_config.rb +17 -11
- data/lib/active_record/database_configurations.rb +86 -33
- data/lib/active_record/delegated_type.rb +8 -3
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +2 -0
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
- data/lib/active_record/encryption/config.rb +25 -1
- data/lib/active_record/encryption/configurable.rb +12 -19
- data/lib/active_record/encryption/context.rb +10 -3
- data/lib/active_record/encryption/contexts.rb +5 -1
- data/lib/active_record/encryption/derived_secret_key_provider.rb +8 -2
- data/lib/active_record/encryption/encryptable_record.rb +36 -18
- data/lib/active_record/encryption/encrypted_attribute_type.rb +17 -6
- data/lib/active_record/encryption/extended_deterministic_queries.rb +66 -54
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +3 -3
- data/lib/active_record/encryption/key_generator.rb +12 -1
- data/lib/active_record/encryption/message_serializer.rb +2 -0
- data/lib/active_record/encryption/properties.rb +3 -3
- data/lib/active_record/encryption/scheme.rb +19 -22
- data/lib/active_record/encryption.rb +1 -0
- data/lib/active_record/enum.rb +113 -26
- data/lib/active_record/errors.rb +108 -15
- data/lib/active_record/explain.rb +23 -3
- data/lib/active_record/fixture_set/model_metadata.rb +14 -4
- data/lib/active_record/fixture_set/render_context.rb +2 -0
- data/lib/active_record/fixture_set/table_row.rb +29 -8
- data/lib/active_record/fixtures.rb +119 -71
- data/lib/active_record/future_result.rb +30 -5
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +30 -16
- data/lib/active_record/insert_all.rb +55 -8
- data/lib/active_record/integration.rb +8 -8
- data/lib/active_record/internal_metadata.rb +120 -30
- data/lib/active_record/locking/pessimistic.rb +5 -2
- data/lib/active_record/log_subscriber.rb +29 -12
- data/lib/active_record/marshalling.rb +56 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
- data/lib/active_record/middleware/database_selector.rb +5 -7
- data/lib/active_record/middleware/shard_selector.rb +3 -1
- data/lib/active_record/migration/command_recorder.rb +104 -5
- data/lib/active_record/migration/compatibility.rb +142 -58
- data/lib/active_record/migration/default_strategy.rb +23 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration.rb +265 -112
- data/lib/active_record/model_schema.rb +60 -40
- data/lib/active_record/nested_attributes.rb +21 -3
- data/lib/active_record/normalization.rb +159 -0
- data/lib/active_record/persistence.rb +187 -35
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +3 -21
- data/lib/active_record/query_logs.rb +77 -52
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +15 -2
- data/lib/active_record/railtie.rb +109 -47
- data/lib/active_record/railties/controller_runtime.rb +12 -8
- data/lib/active_record/railties/databases.rake +139 -145
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +32 -5
- data/lib/active_record/reflection.rb +162 -44
- data/lib/active_record/relation/batches/batch_enumerator.rb +5 -3
- data/lib/active_record/relation/batches.rb +190 -61
- data/lib/active_record/relation/calculations.rb +160 -63
- data/lib/active_record/relation/delegation.rb +22 -8
- data/lib/active_record/relation/finder_methods.rb +77 -16
- data/lib/active_record/relation/merger.rb +2 -0
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +11 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +27 -16
- data/lib/active_record/relation/query_attribute.rb +25 -1
- data/lib/active_record/relation/query_methods.rb +378 -70
- data/lib/active_record/relation/spawn_methods.rb +18 -1
- data/lib/active_record/relation.rb +76 -35
- data/lib/active_record/result.rb +19 -5
- data/lib/active_record/runtime_registry.rb +10 -1
- data/lib/active_record/sanitization.rb +51 -11
- data/lib/active_record/schema.rb +2 -3
- data/lib/active_record/schema_dumper.rb +46 -7
- data/lib/active_record/schema_migration.rb +68 -33
- data/lib/active_record/scoping/default.rb +15 -5
- data/lib/active_record/scoping/named.rb +2 -2
- data/lib/active_record/scoping.rb +2 -1
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/signed_id.rb +7 -5
- data/lib/active_record/store.rb +8 -8
- data/lib/active_record/suppressor.rb +3 -1
- data/lib/active_record/table_metadata.rb +11 -2
- data/lib/active_record/tasks/database_tasks.rb +127 -105
- data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
- data/lib/active_record/tasks/postgresql_database_tasks.rb +16 -13
- data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
- data/lib/active_record/test_fixtures.rb +113 -96
- data/lib/active_record/timestamp.rb +27 -15
- data/lib/active_record/token_for.rb +113 -0
- data/lib/active_record/touch_later.rb +11 -6
- data/lib/active_record/transactions.rb +39 -13
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +4 -0
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/numericality.rb +5 -4
- data/lib/active_record/validations/presence.rb +5 -28
- data/lib/active_record/validations/uniqueness.rb +47 -2
- data/lib/active_record/validations.rb +8 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +121 -16
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/nodes/and.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -1
- data/lib/arel/nodes/bound_sql_literal.rb +61 -0
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/homogeneous_in.rb +0 -8
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/node.rb +111 -2
- data/lib/arel/nodes/sql_literal.rb +6 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes.rb +4 -0
- data/lib/arel/predications.rb +2 -0
- data/lib/arel/table.rb +9 -5
- data/lib/arel/visitors/mysql.rb +8 -1
- data/lib/arel/visitors/to_sql.rb +81 -17
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +16 -2
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/migration.rb +3 -1
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
- metadata +50 -15
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- 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.
|
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.
|
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.
|
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.
|
141
|
-
|
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
|
-
|
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.
|
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.
|
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.
|
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,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
|
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.
|
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
|
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.
|
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.
|
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.
|
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.
|
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.
|
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
|
-
#
|
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
|
-
#
|
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.
|
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,6 +618,13 @@ 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
629
|
# loading a web page if <tt>config.active_record.migration_error</tt> is set to +:page_load+.
|
580
630
|
class CheckPending
|
@@ -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.
|
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
|
-
|
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::
|
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
|
626
|
-
|
627
|
-
|
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
|
-
|
631
|
-
|
632
|
-
|
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
|
-
|
635
|
-
|
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
|
-
|
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
|
-
|
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.
|
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.
|
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.
|
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.
|
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
|
@@ -849,7 +961,7 @@ module ActiveRecord
|
|
849
961
|
end
|
850
962
|
|
851
963
|
time = nil
|
852
|
-
ActiveRecord::
|
964
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection.pool.with_connection do |conn|
|
853
965
|
time = Benchmark.measure do
|
854
966
|
exec_migration(conn, direction)
|
855
967
|
end
|
@@ -874,6 +986,7 @@ module ActiveRecord
|
|
874
986
|
end
|
875
987
|
ensure
|
876
988
|
@connection = nil
|
989
|
+
@execution_strategy = nil
|
877
990
|
end
|
878
991
|
|
879
992
|
def write(text = "")
|
@@ -912,13 +1025,11 @@ module ActiveRecord
|
|
912
1025
|
end
|
913
1026
|
|
914
1027
|
def connection
|
915
|
-
@connection || ActiveRecord::
|
1028
|
+
@connection || ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
916
1029
|
end
|
917
1030
|
|
918
1031
|
def method_missing(method, *arguments, &block)
|
919
|
-
|
920
|
-
|
921
|
-
say_with_time "#{method}(#{arg_list})" do
|
1032
|
+
say_with_time "#{method}(#{format_arguments(arguments)})" do
|
922
1033
|
unless connection.respond_to? :revert
|
923
1034
|
unless arguments.empty? || [:execute, :enable_extension, :disable_extension].include?(method)
|
924
1035
|
arguments[0] = proper_table_name(arguments.first, table_name_options)
|
@@ -928,22 +1039,23 @@ module ActiveRecord
|
|
928
1039
|
end
|
929
1040
|
end
|
930
1041
|
end
|
931
|
-
return super unless
|
932
|
-
|
1042
|
+
return super unless execution_strategy.respond_to?(method)
|
1043
|
+
execution_strategy.send(method, *arguments, &block)
|
933
1044
|
end
|
934
1045
|
end
|
935
1046
|
ruby2_keywords(:method_missing)
|
936
1047
|
|
937
1048
|
def copy(destination, sources, options = {})
|
938
1049
|
copied = []
|
939
|
-
schema_migration = options[:schema_migration] || ActiveRecord::SchemaMigration
|
940
1050
|
|
941
1051
|
FileUtils.mkdir_p(destination) unless File.exist?(destination)
|
1052
|
+
schema_migration = SchemaMigration::NullSchemaMigration.new
|
1053
|
+
internal_metadata = InternalMetadata::NullInternalMetadata.new
|
942
1054
|
|
943
|
-
destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration).migrations
|
1055
|
+
destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration, internal_metadata).migrations
|
944
1056
|
last = destination_migrations.last
|
945
1057
|
sources.each do |scope, path|
|
946
|
-
source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration).migrations
|
1058
|
+
source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration, internal_metadata).migrations
|
947
1059
|
|
948
1060
|
source_migrations.each do |migration|
|
949
1061
|
source = File.binread(migration.filename)
|
@@ -1004,7 +1116,7 @@ module ActiveRecord
|
|
1004
1116
|
if ActiveRecord.timestamped_migrations
|
1005
1117
|
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max
|
1006
1118
|
else
|
1007
|
-
|
1119
|
+
"%.3d" % number.to_i
|
1008
1120
|
end
|
1009
1121
|
end
|
1010
1122
|
|
@@ -1026,6 +1138,22 @@ module ActiveRecord
|
|
1026
1138
|
end
|
1027
1139
|
end
|
1028
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
|
+
|
1029
1157
|
def command_recorder
|
1030
1158
|
CommandRecorder.new(connection)
|
1031
1159
|
end
|
@@ -1058,19 +1186,44 @@ module ActiveRecord
|
|
1058
1186
|
end
|
1059
1187
|
end
|
1060
1188
|
|
1189
|
+
# = \Migration \Context
|
1190
|
+
#
|
1061
1191
|
# MigrationContext sets the context in which a migration is run.
|
1062
1192
|
#
|
1063
1193
|
# A migration context requires the path to the migrations is set
|
1064
1194
|
# in the +migrations_paths+ parameter. Optionally a +schema_migration+
|
1065
|
-
# class can be provided.
|
1066
|
-
#
|
1067
|
-
#
|
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.
|
1068
1198
|
class MigrationContext
|
1069
|
-
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
|
1070
1223
|
|
1071
|
-
def initialize(migrations_paths, schema_migration = SchemaMigration)
|
1072
1224
|
@migrations_paths = migrations_paths
|
1073
|
-
@schema_migration = schema_migration
|
1225
|
+
@schema_migration = schema_migration || SchemaMigration.new(connection)
|
1226
|
+
@internal_metadata = internal_metadata || InternalMetadata.new(connection)
|
1074
1227
|
end
|
1075
1228
|
|
1076
1229
|
# Runs the migrations in the +migrations_path+.
|
@@ -1114,7 +1267,7 @@ module ActiveRecord
|
|
1114
1267
|
migrations
|
1115
1268
|
end
|
1116
1269
|
|
1117
|
-
Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate
|
1270
|
+
Migrator.new(:up, selected_migrations, schema_migration, internal_metadata, target_version).migrate
|
1118
1271
|
end
|
1119
1272
|
|
1120
1273
|
def down(target_version = nil, &block) # :nodoc:
|
@@ -1124,20 +1277,20 @@ module ActiveRecord
|
|
1124
1277
|
migrations
|
1125
1278
|
end
|
1126
1279
|
|
1127
|
-
Migrator.new(:down, selected_migrations, schema_migration, target_version).migrate
|
1280
|
+
Migrator.new(:down, selected_migrations, schema_migration, internal_metadata, target_version).migrate
|
1128
1281
|
end
|
1129
1282
|
|
1130
1283
|
def run(direction, target_version) # :nodoc:
|
1131
|
-
Migrator.new(direction, migrations, schema_migration, target_version).run
|
1284
|
+
Migrator.new(direction, migrations, schema_migration, internal_metadata, target_version).run
|
1132
1285
|
end
|
1133
1286
|
|
1134
1287
|
def open # :nodoc:
|
1135
|
-
Migrator.new(:up, migrations, schema_migration)
|
1288
|
+
Migrator.new(:up, migrations, schema_migration, internal_metadata)
|
1136
1289
|
end
|
1137
1290
|
|
1138
1291
|
def get_all_versions # :nodoc:
|
1139
1292
|
if schema_migration.table_exists?
|
1140
|
-
schema_migration.
|
1293
|
+
schema_migration.integer_versions
|
1141
1294
|
else
|
1142
1295
|
[]
|
1143
1296
|
end
|
@@ -1196,16 +1349,20 @@ module ActiveRecord
|
|
1196
1349
|
end
|
1197
1350
|
|
1198
1351
|
def last_stored_environment # :nodoc:
|
1199
|
-
return nil unless
|
1352
|
+
return nil unless connection.internal_metadata.enabled?
|
1200
1353
|
return nil if current_version == 0
|
1201
|
-
raise NoEnvironmentInSchemaError unless
|
1354
|
+
raise NoEnvironmentInSchemaError unless connection.internal_metadata.table_exists?
|
1202
1355
|
|
1203
|
-
environment =
|
1356
|
+
environment = connection.internal_metadata[:environment]
|
1204
1357
|
raise NoEnvironmentInSchemaError unless environment
|
1205
1358
|
environment
|
1206
1359
|
end
|
1207
1360
|
|
1208
1361
|
private
|
1362
|
+
def connection
|
1363
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
1364
|
+
end
|
1365
|
+
|
1209
1366
|
def migration_files
|
1210
1367
|
paths = Array(migrations_paths)
|
1211
1368
|
Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
|
@@ -1216,7 +1373,7 @@ module ActiveRecord
|
|
1216
1373
|
end
|
1217
1374
|
|
1218
1375
|
def move(direction, steps)
|
1219
|
-
migrator = Migrator.new(direction, migrations, schema_migration)
|
1376
|
+
migrator = Migrator.new(direction, migrations, schema_migration, internal_metadata)
|
1220
1377
|
|
1221
1378
|
if current_version != 0 && !migrator.current_migration
|
1222
1379
|
raise UnknownMigrationVersionError.new(current_version)
|
@@ -1241,23 +1398,28 @@ module ActiveRecord
|
|
1241
1398
|
|
1242
1399
|
# For cases where a table doesn't exist like loading from schema cache
|
1243
1400
|
def current_version
|
1244
|
-
|
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
|
1245
1406
|
end
|
1246
1407
|
end
|
1247
1408
|
|
1248
1409
|
self.migrations_paths = ["db/migrate"]
|
1249
1410
|
|
1250
|
-
def initialize(direction, migrations, schema_migration, target_version = nil)
|
1411
|
+
def initialize(direction, migrations, schema_migration, internal_metadata, target_version = nil)
|
1251
1412
|
@direction = direction
|
1252
1413
|
@target_version = target_version
|
1253
1414
|
@migrated_versions = nil
|
1254
1415
|
@migrations = migrations
|
1255
1416
|
@schema_migration = schema_migration
|
1417
|
+
@internal_metadata = internal_metadata
|
1256
1418
|
|
1257
1419
|
validate(@migrations)
|
1258
1420
|
|
1259
1421
|
@schema_migration.create_table
|
1260
|
-
|
1422
|
+
@internal_metadata.create_table
|
1261
1423
|
end
|
1262
1424
|
|
1263
1425
|
def current_version
|
@@ -1310,18 +1472,21 @@ module ActiveRecord
|
|
1310
1472
|
end
|
1311
1473
|
|
1312
1474
|
def load_migrated
|
1313
|
-
@migrated_versions = Set.new(@schema_migration.
|
1475
|
+
@migrated_versions = Set.new(@schema_migration.integer_versions)
|
1314
1476
|
end
|
1315
1477
|
|
1316
1478
|
private
|
1479
|
+
def connection
|
1480
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
1481
|
+
end
|
1482
|
+
|
1317
1483
|
# Used for running a specific migration.
|
1318
1484
|
def run_without_lock
|
1319
1485
|
migration = migrations.detect { |m| m.version == @target_version }
|
1320
1486
|
raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
|
1321
|
-
result = execute_migration_in_transaction(migration)
|
1322
1487
|
|
1323
1488
|
record_environment
|
1324
|
-
|
1489
|
+
execute_migration_in_transaction(migration)
|
1325
1490
|
end
|
1326
1491
|
|
1327
1492
|
# Used for running multiple migrations up to or down to a certain value.
|
@@ -1330,15 +1495,15 @@ module ActiveRecord
|
|
1330
1495
|
raise UnknownMigrationVersionError.new(@target_version)
|
1331
1496
|
end
|
1332
1497
|
|
1333
|
-
result = runnable.each(&method(:execute_migration_in_transaction))
|
1334
1498
|
record_environment
|
1335
|
-
|
1499
|
+
runnable.each(&method(:execute_migration_in_transaction))
|
1336
1500
|
end
|
1337
1501
|
|
1338
1502
|
# Stores the current environment in the database.
|
1339
1503
|
def record_environment
|
1340
1504
|
return if down?
|
1341
|
-
|
1505
|
+
|
1506
|
+
@internal_metadata[:environment] = connection.pool.db_config.env_name
|
1342
1507
|
end
|
1343
1508
|
|
1344
1509
|
def ran?(migration)
|
@@ -1390,10 +1555,10 @@ module ActiveRecord
|
|
1390
1555
|
def record_version_state_after_migrating(version)
|
1391
1556
|
if down?
|
1392
1557
|
migrated.delete(version)
|
1393
|
-
@schema_migration.
|
1558
|
+
@schema_migration.delete_version(version.to_s)
|
1394
1559
|
else
|
1395
1560
|
migrated << version
|
1396
|
-
@schema_migration.
|
1561
|
+
@schema_migration.create_version(version.to_s)
|
1397
1562
|
end
|
1398
1563
|
end
|
1399
1564
|
|
@@ -1408,50 +1573,38 @@ module ActiveRecord
|
|
1408
1573
|
# Wrap the migration in a transaction only if supported by the adapter.
|
1409
1574
|
def ddl_transaction(migration, &block)
|
1410
1575
|
if use_transaction?(migration)
|
1411
|
-
|
1576
|
+
connection.transaction(&block)
|
1412
1577
|
else
|
1413
1578
|
yield
|
1414
1579
|
end
|
1415
1580
|
end
|
1416
1581
|
|
1417
1582
|
def use_transaction?(migration)
|
1418
|
-
!migration.disable_ddl_transaction &&
|
1583
|
+
!migration.disable_ddl_transaction && connection.supports_ddl_transactions?
|
1419
1584
|
end
|
1420
1585
|
|
1421
1586
|
def use_advisory_lock?
|
1422
|
-
|
1587
|
+
connection.advisory_locks_enabled?
|
1423
1588
|
end
|
1424
1589
|
|
1425
1590
|
def with_advisory_lock
|
1426
1591
|
lock_id = generate_migrator_advisory_lock_id
|
1427
1592
|
|
1428
|
-
|
1429
|
-
|
1430
|
-
|
1431
|
-
|
1432
|
-
yield
|
1433
|
-
ensure
|
1434
|
-
if got_lock && !connection.release_advisory_lock(lock_id)
|
1435
|
-
raise ConcurrentMigrationError.new(
|
1436
|
-
ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
|
1437
|
-
)
|
1438
|
-
end
|
1439
|
-
end
|
1440
|
-
end
|
1441
|
-
|
1442
|
-
def with_advisory_lock_connection(&block)
|
1443
|
-
pool = ActiveRecord::ConnectionAdapters::ConnectionHandler.new.establish_connection(
|
1444
|
-
ActiveRecord::Base.connection_db_config
|
1445
|
-
)
|
1446
|
-
|
1447
|
-
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
|
1448
1597
|
ensure
|
1449
|
-
|
1598
|
+
if got_lock && !connection.release_advisory_lock(lock_id)
|
1599
|
+
raise ConcurrentMigrationError.new(
|
1600
|
+
ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
|
1601
|
+
)
|
1602
|
+
end
|
1450
1603
|
end
|
1451
1604
|
|
1452
1605
|
MIGRATOR_SALT = 2053462845
|
1453
1606
|
def generate_migrator_advisory_lock_id
|
1454
|
-
db_name_hash = Zlib.crc32(
|
1607
|
+
db_name_hash = Zlib.crc32(connection.current_database)
|
1455
1608
|
MIGRATOR_SALT * db_name_hash
|
1456
1609
|
end
|
1457
1610
|
end
|