activerecord 7.0.0 → 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1607 -1040
- data/MIT-LICENSE +1 -1
- data/README.rdoc +17 -18
- 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 +17 -12
- data/lib/active_record/associations/collection_proxy.rb +22 -12
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +27 -17
- data/lib/active_record/associations/has_many_through_association.rb +10 -6
- data/lib/active_record/associations/has_one_association.rb +10 -3
- data/lib/active_record/associations/join_dependency.rb +20 -14
- data/lib/active_record/associations/preloader/association.rb +27 -6
- data/lib/active_record/associations/preloader/through_association.rb +1 -1
- data/lib/active_record/associations/preloader.rb +13 -10
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/associations/through_association.rb +22 -11
- data/lib/active_record/associations.rb +345 -219
- 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 +172 -69
- data/lib/active_record/attribute_methods/write.rb +3 -3
- data/lib/active_record/attribute_methods.rb +110 -28
- data/lib/active_record/attributes.rb +3 -3
- data/lib/active_record/autosave_association.rb +56 -10
- data/lib/active_record/base.rb +10 -5
- data/lib/active_record/callbacks.rb +16 -32
- 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 -34
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +164 -89
- 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 +52 -8
- 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 +163 -29
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +302 -129
- data/lib/active_record/connection_adapters/abstract/transaction.rb +287 -58
- data/lib/active_record/connection_adapters/abstract_adapter.rb +504 -106
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +217 -104
- 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 +29 -12
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +38 -14
- 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 +3 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +72 -45
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -2
- 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 +3 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +41 -8
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +6 -10
- 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 +358 -57
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +343 -181
- 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 +22 -5
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +41 -22
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +242 -81
- 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 +73 -96
- data/lib/active_record/core.rb +136 -148
- data/lib/active_record/counter_cache.rb +46 -25
- data/lib/active_record/database_configurations/connection_url_resolver.rb +1 -0
- 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 +87 -34
- data/lib/active_record/delegated_type.rb +9 -4
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +2 -0
- data/lib/active_record/disable_joins_association_relation.rb +1 -1
- 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 +13 -14
- data/lib/active_record/encryption/context.rb +10 -3
- data/lib/active_record/encryption/contexts.rb +8 -4
- data/lib/active_record/encryption/derived_secret_key_provider.rb +9 -3
- data/lib/active_record/encryption/deterministic_key_provider.rb +1 -1
- data/lib/active_record/encryption/encryptable_record.rb +38 -22
- data/lib/active_record/encryption/encrypted_attribute_type.rb +19 -8
- data/lib/active_record/encryption/encryptor.rb +7 -7
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +3 -3
- data/lib/active_record/encryption/extended_deterministic_queries.rb +83 -71
- 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.rb +1 -1
- data/lib/active_record/encryption/message_serializer.rb +2 -0
- data/lib/active_record/encryption/properties.rb +4 -4
- data/lib/active_record/encryption/scheme.rb +20 -23
- data/lib/active_record/encryption.rb +1 -0
- data/lib/active_record/enum.rb +114 -27
- data/lib/active_record/errors.rb +108 -15
- data/lib/active_record/explain.rb +23 -3
- data/lib/active_record/explain_subscriber.rb +1 -1
- 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 +121 -73
- data/lib/active_record/future_result.rb +30 -5
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/inheritance.rb +30 -16
- data/lib/active_record/insert_all.rb +55 -8
- data/lib/active_record/integration.rb +10 -10
- data/lib/active_record/internal_metadata.rb +118 -30
- data/lib/active_record/locking/optimistic.rb +32 -18
- data/lib/active_record/locking/pessimistic.rb +8 -5
- data/lib/active_record/log_subscriber.rb +39 -17
- 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 +18 -13
- data/lib/active_record/middleware/shard_selector.rb +7 -5
- data/lib/active_record/migration/command_recorder.rb +104 -9
- data/lib/active_record/migration/compatibility.rb +158 -64
- 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 +271 -117
- data/lib/active_record/model_schema.rb +82 -50
- data/lib/active_record/nested_attributes.rb +23 -3
- data/lib/active_record/normalization.rb +159 -0
- data/lib/active_record/persistence.rb +200 -47
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +3 -21
- data/lib/active_record/query_logs.rb +87 -51
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +16 -3
- data/lib/active_record/railtie.rb +127 -61
- data/lib/active_record/railties/controller_runtime.rb +12 -8
- data/lib/active_record/railties/databases.rake +142 -143
- 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 +177 -45
- 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 +200 -83
- data/lib/active_record/relation/delegation.rb +23 -9
- 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 +31 -3
- 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 +26 -14
- data/lib/active_record/relation/query_attribute.rb +25 -1
- data/lib/active_record/relation/query_methods.rb +429 -76
- data/lib/active_record/relation/spawn_methods.rb +18 -1
- data/lib/active_record/relation.rb +98 -41
- data/lib/active_record/result.rb +25 -9
- data/lib/active_record/runtime_registry.rb +10 -1
- data/lib/active_record/sanitization.rb +57 -16
- data/lib/active_record/schema.rb +36 -22
- data/lib/active_record/schema_dumper.rb +65 -23
- data/lib/active_record/schema_migration.rb +68 -33
- data/lib/active_record/scoping/default.rb +20 -12
- 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/serialization.rb +5 -0
- data/lib/active_record/signed_id.rb +9 -7
- data/lib/active_record/store.rb +16 -11
- data/lib/active_record/suppressor.rb +3 -1
- data/lib/active_record/table_metadata.rb +16 -3
- data/lib/active_record/tasks/database_tasks.rb +138 -107
- data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
- data/lib/active_record/tasks/postgresql_database_tasks.rb +17 -15
- data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
- data/lib/active_record/test_fixtures.rb +123 -99
- data/lib/active_record/timestamp.rb +26 -14
- 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/translation.rb +1 -1
- 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 +8 -4
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +3 -3
- 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 +50 -5
- data/lib/active_record/validations.rb +8 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +143 -16
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/filter_predications.rb +1 -1
- 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/filter.rb +1 -1
- 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
|
@@ -326,7 +332,7 @@ module ActiveRecord
|
|
326
332
|
# details.
|
327
333
|
# * <tt>change_table(name, options)</tt>: Allows to make column alterations to
|
328
334
|
# the table called +name+. It makes the table object available to a block that
|
329
|
-
# can then add/remove columns, indexes or foreign keys to it.
|
335
|
+
# can then add/remove columns, indexes, or foreign keys to it.
|
330
336
|
# * <tt>rename_column(table_name, column_name, new_column_name)</tt>: Renames
|
331
337
|
# a column but keeps the type and content.
|
332
338
|
# * <tt>rename_index(table_name, old_name, new_name)</tt>: Renames an index.
|
@@ -356,12 +362,12 @@ module ActiveRecord
|
|
356
362
|
# == Irreversible transformations
|
357
363
|
#
|
358
364
|
# Some transformations are destructive in a manner that cannot be reversed.
|
359
|
-
# Migrations of that kind should raise an
|
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,8 +618,15 @@ module ActiveRecord
|
|
575
618
|
|
576
619
|
MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/ # :nodoc:
|
577
620
|
|
621
|
+
def self.valid_version_format?(version_string) # :nodoc:
|
622
|
+
[
|
623
|
+
MigrationFilenameRegexp,
|
624
|
+
/\A\d(_?\d)*\z/ # integer with optional underscores
|
625
|
+
].any? { |pattern| pattern.match?(version_string) }
|
626
|
+
end
|
627
|
+
|
578
628
|
# This class is used to verify that all migrations have been run before
|
579
|
-
# loading a web page if <tt>config.active_record.migration_error</tt> is set to
|
629
|
+
# loading a web page if <tt>config.active_record.migration_error</tt> is set to +:page_load+.
|
580
630
|
class CheckPending
|
581
631
|
def initialize(app, file_watcher: ActiveSupport::FileUpdateChecker)
|
582
632
|
@app = app
|
@@ -589,7 +639,7 @@ module ActiveRecord
|
|
589
639
|
@mutex.synchronize do
|
590
640
|
@watcher ||= build_watcher do
|
591
641
|
@needs_check = true
|
592
|
-
ActiveRecord::Migration.
|
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
|
@@ -810,8 +922,9 @@ module ActiveRecord
|
|
810
922
|
|
811
923
|
# Runs the given migration classes.
|
812
924
|
# Last argument can specify options:
|
813
|
-
#
|
814
|
-
# -
|
925
|
+
#
|
926
|
+
# - +:direction+ - Default is +:up+.
|
927
|
+
# - +:revert+ - Default is +false+.
|
815
928
|
def run(*migration_classes)
|
816
929
|
opts = migration_classes.extract_options!
|
817
930
|
dir = opts[:direction] || :up
|
@@ -848,7 +961,7 @@ module ActiveRecord
|
|
848
961
|
end
|
849
962
|
|
850
963
|
time = nil
|
851
|
-
ActiveRecord::
|
964
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection.pool.with_connection do |conn|
|
852
965
|
time = Benchmark.measure do
|
853
966
|
exec_migration(conn, direction)
|
854
967
|
end
|
@@ -873,6 +986,7 @@ module ActiveRecord
|
|
873
986
|
end
|
874
987
|
ensure
|
875
988
|
@connection = nil
|
989
|
+
@execution_strategy = nil
|
876
990
|
end
|
877
991
|
|
878
992
|
def write(text = "")
|
@@ -911,13 +1025,11 @@ module ActiveRecord
|
|
911
1025
|
end
|
912
1026
|
|
913
1027
|
def connection
|
914
|
-
@connection || ActiveRecord::
|
1028
|
+
@connection || ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
915
1029
|
end
|
916
1030
|
|
917
1031
|
def method_missing(method, *arguments, &block)
|
918
|
-
|
919
|
-
|
920
|
-
say_with_time "#{method}(#{arg_list})" do
|
1032
|
+
say_with_time "#{method}(#{format_arguments(arguments)})" do
|
921
1033
|
unless connection.respond_to? :revert
|
922
1034
|
unless arguments.empty? || [:execute, :enable_extension, :disable_extension].include?(method)
|
923
1035
|
arguments[0] = proper_table_name(arguments.first, table_name_options)
|
@@ -927,22 +1039,23 @@ module ActiveRecord
|
|
927
1039
|
end
|
928
1040
|
end
|
929
1041
|
end
|
930
|
-
return super unless
|
931
|
-
|
1042
|
+
return super unless execution_strategy.respond_to?(method)
|
1043
|
+
execution_strategy.send(method, *arguments, &block)
|
932
1044
|
end
|
933
1045
|
end
|
934
1046
|
ruby2_keywords(:method_missing)
|
935
1047
|
|
936
1048
|
def copy(destination, sources, options = {})
|
937
1049
|
copied = []
|
938
|
-
schema_migration = options[:schema_migration] || ActiveRecord::SchemaMigration
|
939
1050
|
|
940
1051
|
FileUtils.mkdir_p(destination) unless File.exist?(destination)
|
1052
|
+
schema_migration = SchemaMigration::NullSchemaMigration.new
|
1053
|
+
internal_metadata = InternalMetadata::NullInternalMetadata.new
|
941
1054
|
|
942
|
-
destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration).migrations
|
1055
|
+
destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration, internal_metadata).migrations
|
943
1056
|
last = destination_migrations.last
|
944
1057
|
sources.each do |scope, path|
|
945
|
-
source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration).migrations
|
1058
|
+
source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration, internal_metadata).migrations
|
946
1059
|
|
947
1060
|
source_migrations.each do |migration|
|
948
1061
|
source = File.binread(migration.filename)
|
@@ -1001,9 +1114,9 @@ module ActiveRecord
|
|
1001
1114
|
# Determines the version number of the next migration.
|
1002
1115
|
def next_migration_number(number)
|
1003
1116
|
if ActiveRecord.timestamped_migrations
|
1004
|
-
[Time.now.utc.strftime("%Y%m%d%H%M%S")
|
1117
|
+
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max
|
1005
1118
|
else
|
1006
|
-
|
1119
|
+
"%.3d" % number.to_i
|
1007
1120
|
end
|
1008
1121
|
end
|
1009
1122
|
|
@@ -1025,6 +1138,22 @@ module ActiveRecord
|
|
1025
1138
|
end
|
1026
1139
|
end
|
1027
1140
|
|
1141
|
+
def format_arguments(arguments)
|
1142
|
+
arg_list = arguments[0...-1].map(&:inspect)
|
1143
|
+
last_arg = arguments.last
|
1144
|
+
if last_arg.is_a?(Hash)
|
1145
|
+
last_arg = last_arg.reject { |k, _v| internal_option?(k) }
|
1146
|
+
arg_list << last_arg.inspect unless last_arg.empty?
|
1147
|
+
else
|
1148
|
+
arg_list << last_arg.inspect
|
1149
|
+
end
|
1150
|
+
arg_list.join(", ")
|
1151
|
+
end
|
1152
|
+
|
1153
|
+
def internal_option?(option_name)
|
1154
|
+
option_name.start_with?("_")
|
1155
|
+
end
|
1156
|
+
|
1028
1157
|
def command_recorder
|
1029
1158
|
CommandRecorder.new(connection)
|
1030
1159
|
end
|
@@ -1057,19 +1186,44 @@ module ActiveRecord
|
|
1057
1186
|
end
|
1058
1187
|
end
|
1059
1188
|
|
1189
|
+
# = \Migration \Context
|
1190
|
+
#
|
1060
1191
|
# MigrationContext sets the context in which a migration is run.
|
1061
1192
|
#
|
1062
1193
|
# A migration context requires the path to the migrations is set
|
1063
1194
|
# in the +migrations_paths+ parameter. Optionally a +schema_migration+
|
1064
|
-
# class can be provided.
|
1065
|
-
#
|
1066
|
-
#
|
1195
|
+
# class can be provided. Multiple database applications will instantiate
|
1196
|
+
# a +SchemaMigration+ object per database. From the Rake tasks, \Rails will
|
1197
|
+
# handle this for you.
|
1067
1198
|
class MigrationContext
|
1068
|
-
attr_reader :migrations_paths, :schema_migration
|
1199
|
+
attr_reader :migrations_paths, :schema_migration, :internal_metadata
|
1200
|
+
|
1201
|
+
def initialize(migrations_paths, schema_migration = nil, internal_metadata = nil)
|
1202
|
+
if schema_migration == SchemaMigration
|
1203
|
+
ActiveRecord.deprecator.warn(<<-MSG.squish)
|
1204
|
+
SchemaMigration no longer inherits from ActiveRecord::Base. If you want
|
1205
|
+
to use the default connection, remove this argument. If you want to use a
|
1206
|
+
specific connection, instantiate MigrationContext with the connection's schema
|
1207
|
+
migration, for example `MigrationContext.new(path, Dog.connection.schema_migration)`.
|
1208
|
+
MSG
|
1209
|
+
|
1210
|
+
schema_migration = nil
|
1211
|
+
end
|
1212
|
+
|
1213
|
+
if internal_metadata == InternalMetadata
|
1214
|
+
ActiveRecord.deprecator.warn(<<-MSG.squish)
|
1215
|
+
SchemaMigration no longer inherits from ActiveRecord::Base. If you want
|
1216
|
+
to use the default connection, remove this argument. If you want to use a
|
1217
|
+
specific connection, instantiate MigrationContext with the connection's internal
|
1218
|
+
metadata, for example `MigrationContext.new(path, nil, Dog.connection.internal_metadata)`.
|
1219
|
+
MSG
|
1220
|
+
|
1221
|
+
internal_metadata = nil
|
1222
|
+
end
|
1069
1223
|
|
1070
|
-
def initialize(migrations_paths, schema_migration = SchemaMigration)
|
1071
1224
|
@migrations_paths = migrations_paths
|
1072
|
-
@schema_migration = schema_migration
|
1225
|
+
@schema_migration = schema_migration || SchemaMigration.new(connection)
|
1226
|
+
@internal_metadata = internal_metadata || InternalMetadata.new(connection)
|
1073
1227
|
end
|
1074
1228
|
|
1075
1229
|
# Runs the migrations in the +migrations_path+.
|
@@ -1113,7 +1267,7 @@ module ActiveRecord
|
|
1113
1267
|
migrations
|
1114
1268
|
end
|
1115
1269
|
|
1116
|
-
Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate
|
1270
|
+
Migrator.new(:up, selected_migrations, schema_migration, internal_metadata, target_version).migrate
|
1117
1271
|
end
|
1118
1272
|
|
1119
1273
|
def down(target_version = nil, &block) # :nodoc:
|
@@ -1123,20 +1277,20 @@ module ActiveRecord
|
|
1123
1277
|
migrations
|
1124
1278
|
end
|
1125
1279
|
|
1126
|
-
Migrator.new(:down, selected_migrations, schema_migration, target_version).migrate
|
1280
|
+
Migrator.new(:down, selected_migrations, schema_migration, internal_metadata, target_version).migrate
|
1127
1281
|
end
|
1128
1282
|
|
1129
1283
|
def run(direction, target_version) # :nodoc:
|
1130
|
-
Migrator.new(direction, migrations, schema_migration, target_version).run
|
1284
|
+
Migrator.new(direction, migrations, schema_migration, internal_metadata, target_version).run
|
1131
1285
|
end
|
1132
1286
|
|
1133
1287
|
def open # :nodoc:
|
1134
|
-
Migrator.new(:up, migrations, schema_migration)
|
1288
|
+
Migrator.new(:up, migrations, schema_migration, internal_metadata)
|
1135
1289
|
end
|
1136
1290
|
|
1137
1291
|
def get_all_versions # :nodoc:
|
1138
1292
|
if schema_migration.table_exists?
|
1139
|
-
schema_migration.
|
1293
|
+
schema_migration.integer_versions
|
1140
1294
|
else
|
1141
1295
|
[]
|
1142
1296
|
end
|
@@ -1195,16 +1349,20 @@ module ActiveRecord
|
|
1195
1349
|
end
|
1196
1350
|
|
1197
1351
|
def last_stored_environment # :nodoc:
|
1198
|
-
return nil unless
|
1352
|
+
return nil unless connection.internal_metadata.enabled?
|
1199
1353
|
return nil if current_version == 0
|
1200
|
-
raise NoEnvironmentInSchemaError unless
|
1354
|
+
raise NoEnvironmentInSchemaError unless connection.internal_metadata.table_exists?
|
1201
1355
|
|
1202
|
-
environment =
|
1356
|
+
environment = connection.internal_metadata[:environment]
|
1203
1357
|
raise NoEnvironmentInSchemaError unless environment
|
1204
1358
|
environment
|
1205
1359
|
end
|
1206
1360
|
|
1207
1361
|
private
|
1362
|
+
def connection
|
1363
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
1364
|
+
end
|
1365
|
+
|
1208
1366
|
def migration_files
|
1209
1367
|
paths = Array(migrations_paths)
|
1210
1368
|
Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
|
@@ -1215,7 +1373,7 @@ module ActiveRecord
|
|
1215
1373
|
end
|
1216
1374
|
|
1217
1375
|
def move(direction, steps)
|
1218
|
-
migrator = Migrator.new(direction, migrations, schema_migration)
|
1376
|
+
migrator = Migrator.new(direction, migrations, schema_migration, internal_metadata)
|
1219
1377
|
|
1220
1378
|
if current_version != 0 && !migrator.current_migration
|
1221
1379
|
raise UnknownMigrationVersionError.new(current_version)
|
@@ -1240,23 +1398,28 @@ module ActiveRecord
|
|
1240
1398
|
|
1241
1399
|
# For cases where a table doesn't exist like loading from schema cache
|
1242
1400
|
def current_version
|
1243
|
-
|
1401
|
+
connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
1402
|
+
schema_migration = SchemaMigration.new(connection)
|
1403
|
+
internal_metadata = InternalMetadata.new(connection)
|
1404
|
+
|
1405
|
+
MigrationContext.new(migrations_paths, schema_migration, internal_metadata).current_version
|
1244
1406
|
end
|
1245
1407
|
end
|
1246
1408
|
|
1247
1409
|
self.migrations_paths = ["db/migrate"]
|
1248
1410
|
|
1249
|
-
def initialize(direction, migrations, schema_migration, target_version = nil)
|
1411
|
+
def initialize(direction, migrations, schema_migration, internal_metadata, target_version = nil)
|
1250
1412
|
@direction = direction
|
1251
1413
|
@target_version = target_version
|
1252
1414
|
@migrated_versions = nil
|
1253
1415
|
@migrations = migrations
|
1254
1416
|
@schema_migration = schema_migration
|
1417
|
+
@internal_metadata = internal_metadata
|
1255
1418
|
|
1256
1419
|
validate(@migrations)
|
1257
1420
|
|
1258
1421
|
@schema_migration.create_table
|
1259
|
-
|
1422
|
+
@internal_metadata.create_table
|
1260
1423
|
end
|
1261
1424
|
|
1262
1425
|
def current_version
|
@@ -1309,18 +1472,21 @@ module ActiveRecord
|
|
1309
1472
|
end
|
1310
1473
|
|
1311
1474
|
def load_migrated
|
1312
|
-
@migrated_versions = Set.new(@schema_migration.
|
1475
|
+
@migrated_versions = Set.new(@schema_migration.integer_versions)
|
1313
1476
|
end
|
1314
1477
|
|
1315
1478
|
private
|
1479
|
+
def connection
|
1480
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
1481
|
+
end
|
1482
|
+
|
1316
1483
|
# Used for running a specific migration.
|
1317
1484
|
def run_without_lock
|
1318
1485
|
migration = migrations.detect { |m| m.version == @target_version }
|
1319
1486
|
raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
|
1320
|
-
result = execute_migration_in_transaction(migration)
|
1321
1487
|
|
1322
1488
|
record_environment
|
1323
|
-
|
1489
|
+
execute_migration_in_transaction(migration)
|
1324
1490
|
end
|
1325
1491
|
|
1326
1492
|
# Used for running multiple migrations up to or down to a certain value.
|
@@ -1329,15 +1495,15 @@ module ActiveRecord
|
|
1329
1495
|
raise UnknownMigrationVersionError.new(@target_version)
|
1330
1496
|
end
|
1331
1497
|
|
1332
|
-
result = runnable.each(&method(:execute_migration_in_transaction))
|
1333
1498
|
record_environment
|
1334
|
-
|
1499
|
+
runnable.each(&method(:execute_migration_in_transaction))
|
1335
1500
|
end
|
1336
1501
|
|
1337
1502
|
# Stores the current environment in the database.
|
1338
1503
|
def record_environment
|
1339
1504
|
return if down?
|
1340
|
-
|
1505
|
+
|
1506
|
+
@internal_metadata[:environment] = connection.pool.db_config.env_name
|
1341
1507
|
end
|
1342
1508
|
|
1343
1509
|
def ran?(migration)
|
@@ -1389,10 +1555,10 @@ module ActiveRecord
|
|
1389
1555
|
def record_version_state_after_migrating(version)
|
1390
1556
|
if down?
|
1391
1557
|
migrated.delete(version)
|
1392
|
-
@schema_migration.
|
1558
|
+
@schema_migration.delete_version(version.to_s)
|
1393
1559
|
else
|
1394
1560
|
migrated << version
|
1395
|
-
@schema_migration.
|
1561
|
+
@schema_migration.create_version(version.to_s)
|
1396
1562
|
end
|
1397
1563
|
end
|
1398
1564
|
|
@@ -1407,50 +1573,38 @@ module ActiveRecord
|
|
1407
1573
|
# Wrap the migration in a transaction only if supported by the adapter.
|
1408
1574
|
def ddl_transaction(migration, &block)
|
1409
1575
|
if use_transaction?(migration)
|
1410
|
-
|
1576
|
+
connection.transaction(&block)
|
1411
1577
|
else
|
1412
1578
|
yield
|
1413
1579
|
end
|
1414
1580
|
end
|
1415
1581
|
|
1416
1582
|
def use_transaction?(migration)
|
1417
|
-
!migration.disable_ddl_transaction &&
|
1583
|
+
!migration.disable_ddl_transaction && connection.supports_ddl_transactions?
|
1418
1584
|
end
|
1419
1585
|
|
1420
1586
|
def use_advisory_lock?
|
1421
|
-
|
1587
|
+
connection.advisory_locks_enabled?
|
1422
1588
|
end
|
1423
1589
|
|
1424
1590
|
def with_advisory_lock
|
1425
1591
|
lock_id = generate_migrator_advisory_lock_id
|
1426
1592
|
|
1427
|
-
|
1428
|
-
|
1429
|
-
|
1430
|
-
|
1431
|
-
yield
|
1432
|
-
ensure
|
1433
|
-
if got_lock && !connection.release_advisory_lock(lock_id)
|
1434
|
-
raise ConcurrentMigrationError.new(
|
1435
|
-
ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
|
1436
|
-
)
|
1437
|
-
end
|
1438
|
-
end
|
1439
|
-
end
|
1440
|
-
|
1441
|
-
def with_advisory_lock_connection(&block)
|
1442
|
-
pool = ActiveRecord::ConnectionAdapters::ConnectionHandler.new.establish_connection(
|
1443
|
-
ActiveRecord::Base.connection_db_config
|
1444
|
-
)
|
1445
|
-
|
1446
|
-
pool.with_connection(&block)
|
1593
|
+
got_lock = connection.get_advisory_lock(lock_id)
|
1594
|
+
raise ConcurrentMigrationError unless got_lock
|
1595
|
+
load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
|
1596
|
+
yield
|
1447
1597
|
ensure
|
1448
|
-
|
1598
|
+
if got_lock && !connection.release_advisory_lock(lock_id)
|
1599
|
+
raise ConcurrentMigrationError.new(
|
1600
|
+
ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
|
1601
|
+
)
|
1602
|
+
end
|
1449
1603
|
end
|
1450
1604
|
|
1451
1605
|
MIGRATOR_SALT = 2053462845
|
1452
1606
|
def generate_migrator_advisory_lock_id
|
1453
|
-
db_name_hash = Zlib.crc32(
|
1607
|
+
db_name_hash = Zlib.crc32(connection.current_database)
|
1454
1608
|
MIGRATOR_SALT * db_name_hash
|
1455
1609
|
end
|
1456
1610
|
end
|