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