activerecord 6.1.7 → 7.1.5
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 +2030 -1020
- data/MIT-LICENSE +1 -1
- data/README.rdoc +18 -18
- data/lib/active_record/aggregations.rb +17 -14
- data/lib/active_record/association_relation.rb +1 -11
- data/lib/active_record/associations/association.rb +51 -19
- data/lib/active_record/associations/association_scope.rb +17 -12
- data/lib/active_record/associations/belongs_to_association.rb +28 -9
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
- data/lib/active_record/associations/builder/association.rb +11 -5
- data/lib/active_record/associations/builder/belongs_to.rb +40 -14
- data/lib/active_record/associations/builder/collection_association.rb +10 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
- data/lib/active_record/associations/builder/has_many.rb +3 -2
- data/lib/active_record/associations/builder/has_one.rb +2 -1
- data/lib/active_record/associations/builder/singular_association.rb +6 -2
- data/lib/active_record/associations/collection_association.rb +39 -35
- data/lib/active_record/associations/collection_proxy.rb +30 -15
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +28 -18
- data/lib/active_record/associations/has_many_through_association.rb +12 -7
- data/lib/active_record/associations/has_one_association.rb +20 -10
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +3 -2
- data/lib/active_record/associations/join_dependency.rb +28 -20
- data/lib/active_record/associations/preloader/association.rb +210 -52
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +50 -14
- data/lib/active_record/associations/preloader.rb +50 -121
- data/lib/active_record/associations/singular_association.rb +9 -3
- data/lib/active_record/associations/through_association.rb +25 -14
- data/lib/active_record/associations.rb +446 -306
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +1 -3
- data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
- data/lib/active_record/attribute_methods/dirty.rb +73 -22
- data/lib/active_record/attribute_methods/primary_key.rb +78 -26
- data/lib/active_record/attribute_methods/query.rb +31 -19
- data/lib/active_record/attribute_methods/read.rb +27 -12
- data/lib/active_record/attribute_methods/serialization.rb +194 -37
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +8 -3
- data/lib/active_record/attribute_methods/write.rb +12 -15
- data/lib/active_record/attribute_methods.rb +161 -40
- data/lib/active_record/attributes.rb +27 -38
- data/lib/active_record/autosave_association.rb +65 -31
- data/lib/active_record/base.rb +25 -2
- data/lib/active_record/callbacks.rb +18 -34
- 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 -46
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +367 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +78 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +113 -597
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +172 -50
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +87 -73
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +21 -20
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +186 -31
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +367 -141
- data/lib/active_record/connection_adapters/abstract/transaction.rb +281 -59
- data/lib/active_record/connection_adapters/abstract_adapter.rb +631 -150
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +317 -164
- data/lib/active_record/connection_adapters/column.rb +13 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +25 -134
- data/lib/active_record/connection_adapters/mysql/quoting.rb +56 -25
- 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 +39 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +151 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +112 -55
- data/lib/active_record/connection_adapters/pool_config.rb +20 -11
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +89 -52
- 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/date.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +12 -3
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -56
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +92 -2
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +153 -3
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +397 -75
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +508 -246
- data/lib/active_record/connection_adapters/schema_cache.rb +319 -90
- data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +72 -53
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +37 -21
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -22
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +296 -104
- 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 +9 -6
- data/lib/active_record/connection_handling.rb +108 -137
- data/lib/active_record/core.rb +242 -233
- data/lib/active_record/counter_cache.rb +52 -27
- data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -2
- data/lib/active_record/database_configurations/database_config.rb +21 -12
- data/lib/active_record/database_configurations/hash_config.rb +88 -16
- data/lib/active_record/database_configurations/url_config.rb +18 -12
- data/lib/active_record/database_configurations.rb +95 -59
- data/lib/active_record/delegated_type.rb +66 -20
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +4 -2
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +1 -1
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +68 -0
- data/lib/active_record/encryption/configurable.rb +60 -0
- data/lib/active_record/encryption/context.rb +42 -0
- data/lib/active_record/encryption/contexts.rb +76 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +230 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +155 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +155 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +53 -0
- data/lib/active_record/encryption/key_provider.rb +46 -0
- data/lib/active_record/encryption/message.rb +33 -0
- data/lib/active_record/encryption/message_serializer.rb +92 -0
- data/lib/active_record/encryption/null_encryptor.rb +21 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
- data/lib/active_record/encryption/scheme.rb +100 -0
- data/lib/active_record/encryption.rb +58 -0
- data/lib/active_record/enum.rb +154 -63
- data/lib/active_record/errors.rb +172 -15
- data/lib/active_record/explain.rb +23 -3
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +15 -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 +70 -14
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +147 -86
- data/lib/active_record/future_result.rb +174 -0
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +81 -29
- data/lib/active_record/insert_all.rb +135 -22
- data/lib/active_record/integration.rb +11 -10
- data/lib/active_record/internal_metadata.rb +119 -33
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +37 -22
- data/lib/active_record/locking/pessimistic.rb +15 -6
- data/lib/active_record/log_subscriber.rb +52 -19
- 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 +10 -10
- data/lib/active_record/middleware/database_selector.rb +23 -13
- data/lib/active_record/middleware/shard_selector.rb +62 -0
- data/lib/active_record/migration/command_recorder.rb +112 -14
- data/lib/active_record/migration/compatibility.rb +233 -46
- 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/join_table.rb +1 -1
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +361 -173
- data/lib/active_record/model_schema.rb +125 -101
- data/lib/active_record/nested_attributes.rb +50 -20
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/normalization.rb +167 -0
- data/lib/active_record/persistence.rb +409 -88
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +4 -22
- data/lib/active_record/query_logs.rb +174 -0
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +29 -6
- data/lib/active_record/railtie.rb +220 -44
- data/lib/active_record/railties/controller_runtime.rb +15 -10
- data/lib/active_record/railties/databases.rake +188 -252
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +41 -3
- data/lib/active_record/reflection.rb +248 -81
- data/lib/active_record/relation/batches/batch_enumerator.rb +23 -7
- data/lib/active_record/relation/batches.rb +192 -63
- data/lib/active_record/relation/calculations.rb +246 -90
- data/lib/active_record/relation/delegation.rb +28 -14
- data/lib/active_record/relation/finder_methods.rb +108 -51
- data/lib/active_record/relation/merger.rb +22 -13
- 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 +27 -20
- data/lib/active_record/relation/query_attribute.rb +30 -12
- data/lib/active_record/relation/query_methods.rb +670 -129
- data/lib/active_record/relation/record_fetch_warning.rb +7 -9
- data/lib/active_record/relation/spawn_methods.rb +20 -3
- data/lib/active_record/relation/where_clause.rb +10 -19
- data/lib/active_record/relation.rb +287 -120
- data/lib/active_record/result.rb +37 -11
- data/lib/active_record/runtime_registry.rb +32 -13
- data/lib/active_record/sanitization.rb +65 -20
- data/lib/active_record/schema.rb +36 -22
- data/lib/active_record/schema_dumper.rb +73 -24
- data/lib/active_record/schema_migration.rb +68 -33
- data/lib/active_record/scoping/default.rb +72 -15
- data/lib/active_record/scoping/named.rb +5 -13
- data/lib/active_record/scoping.rb +65 -34
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/serialization.rb +6 -1
- data/lib/active_record/signed_id.rb +10 -8
- data/lib/active_record/store.rb +10 -10
- data/lib/active_record/suppressor.rb +13 -15
- data/lib/active_record/table_metadata.rb +16 -3
- data/lib/active_record/tasks/database_tasks.rb +251 -140
- data/lib/active_record/tasks/mysql_database_tasks.rb +16 -7
- data/lib/active_record/tasks/postgresql_database_tasks.rb +35 -26
- data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +117 -96
- data/lib/active_record/timestamp.rb +32 -19
- data/lib/active_record/token_for.rb +113 -0
- data/lib/active_record/touch_later.rb +11 -6
- data/lib/active_record/transactions.rb +48 -27
- data/lib/active_record/translation.rb +3 -3
- data/lib/active_record/type/adapter_specific_registry.rb +32 -14
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +9 -5
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/type/type_map.rb +17 -20
- data/lib/active_record/type.rb +1 -2
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +4 -4
- 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 +51 -6
- data/lib/active_record/validations.rb +8 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +335 -32
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/crud.rb +28 -22
- data/lib/arel/delete_manager.rb +18 -4
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +2 -3
- 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/casted.rb +1 -1
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/delete_statement.rb +12 -13
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/homogeneous_in.rb +1 -9
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/node.rb +111 -2
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +6 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes/update_statement.rb +8 -3
- data/lib/arel/nodes.rb +5 -0
- data/lib/arel/predications.rb +13 -3
- data/lib/arel/select_manager.rb +10 -4
- data/lib/arel/table.rb +9 -6
- data/lib/arel/tree_manager.rb +5 -13
- data/lib/arel/update_manager.rb +18 -4
- data/lib/arel/visitors/dot.rb +80 -90
- data/lib/arel/visitors/mysql.rb +16 -3
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +141 -20
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +18 -3
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- 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
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
- data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
- data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
- metadata +96 -16
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -67
@@ -7,9 +7,10 @@ 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
|
-
class MigrationError < ActiveRecordError
|
13
|
+
class MigrationError < ActiveRecordError # :nodoc:
|
13
14
|
def initialize(message = nil)
|
14
15
|
message = "\n\n#{message}\n\n" if message
|
15
16
|
super
|
@@ -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[
|
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[
|
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[
|
67
|
+
# class ReversibleMigrationExample < ActiveRecord::Migration[7.1]
|
67
68
|
# def change
|
68
69
|
# create_table :distributors do |t|
|
69
70
|
# t.string :zipcode
|
@@ -90,7 +91,7 @@ module ActiveRecord
|
|
90
91
|
class IrreversibleMigration < MigrationError
|
91
92
|
end
|
92
93
|
|
93
|
-
class DuplicateMigrationVersionError < MigrationError
|
94
|
+
class DuplicateMigrationVersionError < MigrationError # :nodoc:
|
94
95
|
def initialize(version = nil)
|
95
96
|
if version
|
96
97
|
super("Multiple migrations have the version number #{version}.")
|
@@ -100,7 +101,7 @@ module ActiveRecord
|
|
100
101
|
end
|
101
102
|
end
|
102
103
|
|
103
|
-
class DuplicateMigrationNameError < MigrationError
|
104
|
+
class DuplicateMigrationNameError < MigrationError # :nodoc:
|
104
105
|
def initialize(name = nil)
|
105
106
|
if name
|
106
107
|
super("Multiple migrations have the name #{name}.")
|
@@ -110,7 +111,7 @@ module ActiveRecord
|
|
110
111
|
end
|
111
112
|
end
|
112
113
|
|
113
|
-
class UnknownMigrationVersionError < MigrationError
|
114
|
+
class UnknownMigrationVersionError < MigrationError # :nodoc:
|
114
115
|
def initialize(version = nil)
|
115
116
|
if version
|
116
117
|
super("No migration with version number #{version}.")
|
@@ -120,7 +121,7 @@ module ActiveRecord
|
|
120
121
|
end
|
121
122
|
end
|
122
123
|
|
123
|
-
class IllegalMigrationNameError < MigrationError
|
124
|
+
class IllegalMigrationNameError < MigrationError # :nodoc:
|
124
125
|
def initialize(name = nil)
|
125
126
|
if name
|
126
127
|
super("Illegal name for migration file: #{name}\n\t(only lower case letters, numbers, and '_' allowed).")
|
@@ -130,42 +131,48 @@ module ActiveRecord
|
|
130
131
|
end
|
131
132
|
end
|
132
133
|
|
133
|
-
class PendingMigrationError < MigrationError
|
134
|
+
class PendingMigrationError < MigrationError # :nodoc:
|
134
135
|
include ActiveSupport::ActionableError
|
135
136
|
|
136
137
|
action "Run pending migrations" do
|
137
138
|
ActiveRecord::Tasks::DatabaseTasks.migrate
|
138
139
|
|
139
|
-
if ActiveRecord
|
140
|
-
ActiveRecord::Tasks::DatabaseTasks.
|
141
|
-
|
142
|
-
)
|
140
|
+
if ActiveRecord.dump_schema_after_migration
|
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
|
-
class ConcurrentMigrationError < MigrationError
|
175
|
+
class ConcurrentMigrationError < MigrationError # :nodoc:
|
169
176
|
DEFAULT_MESSAGE = "Cannot run migrations because another migration process is currently running."
|
170
177
|
RELEASE_LOCK_FAILED_MESSAGE = "Failed to release advisory lock"
|
171
178
|
|
@@ -174,7 +181,7 @@ module ActiveRecord
|
|
174
181
|
end
|
175
182
|
end
|
176
183
|
|
177
|
-
class NoEnvironmentInSchemaError < MigrationError
|
184
|
+
class NoEnvironmentInSchemaError < MigrationError # :nodoc:
|
178
185
|
def initialize
|
179
186
|
msg = "Environment data not found in the schema. To resolve this issue, run: \n\n bin/rails db:environment:set"
|
180
187
|
if defined?(Rails.env)
|
@@ -185,7 +192,7 @@ module ActiveRecord
|
|
185
192
|
end
|
186
193
|
end
|
187
194
|
|
188
|
-
class ProtectedEnvironmentError < ActiveRecordError
|
195
|
+
class ProtectedEnvironmentError < ActiveRecordError # :nodoc:
|
189
196
|
def initialize(env = "production")
|
190
197
|
msg = +"You are attempting to run a destructive action against your '#{env}' database.\n"
|
191
198
|
msg << "If you are sure you want to continue, run the same command with the environment variable:\n"
|
@@ -228,7 +235,7 @@ module ActiveRecord
|
|
228
235
|
#
|
229
236
|
# Example of a simple migration:
|
230
237
|
#
|
231
|
-
# class AddSsl < ActiveRecord::Migration[
|
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[
|
258
|
+
# class AddSystemSettings < ActiveRecord::Migration[7.1]
|
252
259
|
# def up
|
253
260
|
# create_table :system_settings do |t|
|
254
261
|
# t.string :name
|
@@ -326,7 +333,7 @@ module ActiveRecord
|
|
326
333
|
# details.
|
327
334
|
# * <tt>change_table(name, options)</tt>: Allows to make column alterations to
|
328
335
|
# 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.
|
336
|
+
# can then add/remove columns, indexes, or foreign keys to it.
|
330
337
|
# * <tt>rename_column(table_name, column_name, new_column_name)</tt>: Renames
|
331
338
|
# a column but keeps the type and content.
|
332
339
|
# * <tt>rename_index(table_name, old_name, new_name)</tt>: Renames an index.
|
@@ -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[
|
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[
|
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[
|
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[
|
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[
|
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[
|
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[
|
545
|
+
# class ChangeEnum < ActiveRecord::Migration[7.1]
|
538
546
|
# disable_ddl_transaction!
|
539
547
|
#
|
540
548
|
# def up
|
@@ -548,18 +556,57 @@ 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
|
-
class Current < Migration
|
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
|
-
def self.inherited(subclass)
|
601
|
+
def self.inherited(subclass) # :nodoc:
|
557
602
|
super
|
558
603
|
if subclass.superclass == Migration
|
604
|
+
major = ActiveRecord::VERSION::MAJOR
|
605
|
+
minor = ActiveRecord::VERSION::MINOR
|
559
606
|
raise StandardError, "Directly inheriting from ActiveRecord::Migration is not supported. " \
|
560
|
-
"Please specify the
|
607
|
+
"Please specify the Active Record release the migration was written for:\n" \
|
561
608
|
"\n" \
|
562
|
-
" class #{subclass} < ActiveRecord::Migration[
|
609
|
+
" class #{subclass} < ActiveRecord::Migration[#{major}.#{minor}]"
|
563
610
|
end
|
564
611
|
end
|
565
612
|
|
@@ -571,10 +618,17 @@ module ActiveRecord
|
|
571
618
|
ActiveRecord::VERSION::STRING.to_f
|
572
619
|
end
|
573
620
|
|
574
|
-
MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/
|
621
|
+
MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/ # :nodoc:
|
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
|
575
629
|
|
576
630
|
# This class is used to verify that all migrations have been run before
|
577
|
-
# loading a web page if <tt>config.active_record.migration_error</tt> is set to
|
631
|
+
# loading a web page if <tt>config.active_record.migration_error</tt> is set to +:page_load+.
|
578
632
|
class CheckPending
|
579
633
|
def initialize(app, file_watcher: ActiveSupport::FileUpdateChecker)
|
580
634
|
@app = app
|
@@ -587,7 +641,7 @@ module ActiveRecord
|
|
587
641
|
@mutex.synchronize do
|
588
642
|
@watcher ||= build_watcher do
|
589
643
|
@needs_check = true
|
590
|
-
ActiveRecord::Migration.
|
644
|
+
ActiveRecord::Migration.check_pending_migrations
|
591
645
|
@needs_check = false
|
592
646
|
end
|
593
647
|
|
@@ -603,61 +657,84 @@ module ActiveRecord
|
|
603
657
|
|
604
658
|
private
|
605
659
|
def build_watcher(&block)
|
606
|
-
|
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
|
607
663
|
@file_watcher.new([], paths.index_with(["rb"]), &block)
|
608
664
|
end
|
609
665
|
|
610
666
|
def connection
|
611
|
-
ActiveRecord::
|
667
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
612
668
|
end
|
613
669
|
end
|
614
670
|
|
615
671
|
class << self
|
616
|
-
attr_accessor :delegate
|
617
|
-
attr_accessor :disable_ddl_transaction
|
672
|
+
attr_accessor :delegate # :nodoc:
|
673
|
+
attr_accessor :disable_ddl_transaction # :nodoc:
|
618
674
|
|
619
|
-
def nearest_delegate
|
675
|
+
def nearest_delegate # :nodoc:
|
620
676
|
delegate || superclass.nearest_delegate
|
621
677
|
end
|
622
678
|
|
623
|
-
# Raises
|
624
|
-
|
625
|
-
|
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
|
626
694
|
end
|
627
695
|
|
628
|
-
|
629
|
-
|
630
|
-
|
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 = []
|
700
|
+
|
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
|
705
|
+
end
|
706
|
+
|
707
|
+
migrations = pending_migrations.flatten
|
631
708
|
|
632
|
-
|
633
|
-
|
709
|
+
if migrations.any?
|
710
|
+
raise ActiveRecord::PendingMigrationError.new(pending_migrations: migrations)
|
634
711
|
end
|
712
|
+
end
|
635
713
|
|
636
|
-
|
714
|
+
def load_schema_if_pending!
|
715
|
+
if any_schema_needs_update?
|
637
716
|
# Roundtrip to Rake to allow plugins to hook into database initialization.
|
638
717
|
root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
|
718
|
+
|
639
719
|
FileUtils.cd(root) do
|
640
|
-
Base.clear_all_connections!
|
720
|
+
Base.connection_handler.clear_all_connections!(:all)
|
641
721
|
system("bin/rails db:test:prepare")
|
642
722
|
end
|
643
723
|
end
|
644
724
|
|
645
|
-
|
646
|
-
Base.establish_connection(current_db_config)
|
647
|
-
|
648
|
-
check_pending!
|
725
|
+
check_pending_migrations
|
649
726
|
end
|
650
727
|
|
651
|
-
def maintain_test_schema!
|
652
|
-
if ActiveRecord
|
728
|
+
def maintain_test_schema! # :nodoc:
|
729
|
+
if ActiveRecord.maintain_test_schema
|
653
730
|
suppress_messages { load_schema_if_pending! }
|
654
731
|
end
|
655
732
|
end
|
656
733
|
|
657
|
-
def method_missing(name, *args, &block)
|
734
|
+
def method_missing(name, *args, &block) # :nodoc:
|
658
735
|
nearest_delegate.send(name, *args, &block)
|
659
736
|
end
|
660
|
-
ruby2_keywords(:method_missing)
|
737
|
+
ruby2_keywords(:method_missing)
|
661
738
|
|
662
739
|
def migrate(direction)
|
663
740
|
new.migrate direction
|
@@ -670,9 +747,46 @@ module ActiveRecord
|
|
670
747
|
def disable_ddl_transaction!
|
671
748
|
@disable_ddl_transaction = true
|
672
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
|
673
787
|
end
|
674
788
|
|
675
|
-
def disable_ddl_transaction
|
789
|
+
def disable_ddl_transaction # :nodoc:
|
676
790
|
self.class.disable_ddl_transaction
|
677
791
|
end
|
678
792
|
|
@@ -685,6 +799,10 @@ module ActiveRecord
|
|
685
799
|
@connection = nil
|
686
800
|
end
|
687
801
|
|
802
|
+
def execution_strategy
|
803
|
+
@execution_strategy ||= ActiveRecord.migration_strategy.new(self)
|
804
|
+
end
|
805
|
+
|
688
806
|
self.verbose = true
|
689
807
|
# instantiate the delegate object after initialize is defined
|
690
808
|
self.delegate = new
|
@@ -696,7 +814,7 @@ module ActiveRecord
|
|
696
814
|
# and create the table 'apples' on the way up, and the reverse
|
697
815
|
# on the way down.
|
698
816
|
#
|
699
|
-
# class FixTLMigration < ActiveRecord::Migration[
|
817
|
+
# class FixTLMigration < ActiveRecord::Migration[7.1]
|
700
818
|
# def change
|
701
819
|
# revert do
|
702
820
|
# create_table(:horses) do |t|
|
@@ -715,7 +833,7 @@ module ActiveRecord
|
|
715
833
|
#
|
716
834
|
# require_relative "20121212123456_tenderlove_migration"
|
717
835
|
#
|
718
|
-
# class FixupTLMigration < ActiveRecord::Migration[
|
836
|
+
# class FixupTLMigration < ActiveRecord::Migration[7.1]
|
719
837
|
# def change
|
720
838
|
# revert TenderloveMigration
|
721
839
|
#
|
@@ -726,16 +844,16 @@ module ActiveRecord
|
|
726
844
|
# end
|
727
845
|
#
|
728
846
|
# This command can be nested.
|
729
|
-
def revert(*migration_classes)
|
847
|
+
def revert(*migration_classes, &block)
|
730
848
|
run(*migration_classes.reverse, revert: true) unless migration_classes.empty?
|
731
849
|
if block_given?
|
732
850
|
if connection.respond_to? :revert
|
733
|
-
connection.revert
|
851
|
+
connection.revert(&block)
|
734
852
|
else
|
735
853
|
recorder = command_recorder
|
736
854
|
@connection = recorder
|
737
855
|
suppress_messages do
|
738
|
-
connection.revert
|
856
|
+
connection.revert(&block)
|
739
857
|
end
|
740
858
|
@connection = recorder.delegate
|
741
859
|
recorder.replay(self)
|
@@ -747,7 +865,7 @@ module ActiveRecord
|
|
747
865
|
connection.respond_to?(:reverting) && connection.reverting
|
748
866
|
end
|
749
867
|
|
750
|
-
ReversibleBlockHelper = Struct.new(:reverting) do
|
868
|
+
ReversibleBlockHelper = Struct.new(:reverting) do # :nodoc:
|
751
869
|
def up
|
752
870
|
yield unless reverting
|
753
871
|
end
|
@@ -766,7 +884,7 @@ module ActiveRecord
|
|
766
884
|
# when the three columns 'first_name', 'last_name' and 'full_name' exist,
|
767
885
|
# even when migrating down:
|
768
886
|
#
|
769
|
-
# class SplitNameMigration < ActiveRecord::Migration[
|
887
|
+
# class SplitNameMigration < ActiveRecord::Migration[7.1]
|
770
888
|
# def change
|
771
889
|
# add_column :users, :first_name, :string
|
772
890
|
# add_column :users, :last_name, :string
|
@@ -794,7 +912,7 @@ module ActiveRecord
|
|
794
912
|
# In the following example, the new column +published+ will be given
|
795
913
|
# the value +true+ for all existing records.
|
796
914
|
#
|
797
|
-
# class AddPublishedToPosts < ActiveRecord::Migration[
|
915
|
+
# class AddPublishedToPosts < ActiveRecord::Migration[7.1]
|
798
916
|
# def change
|
799
917
|
# add_column :posts, :published, :boolean, default: false
|
800
918
|
# up_only do
|
@@ -802,14 +920,15 @@ module ActiveRecord
|
|
802
920
|
# end
|
803
921
|
# end
|
804
922
|
# end
|
805
|
-
def up_only
|
806
|
-
execute_block
|
923
|
+
def up_only(&block)
|
924
|
+
execute_block(&block) unless reverting?
|
807
925
|
end
|
808
926
|
|
809
927
|
# Runs the given migration classes.
|
810
928
|
# Last argument can specify options:
|
811
|
-
#
|
812
|
-
# -
|
929
|
+
#
|
930
|
+
# - +:direction+ - Default is +:up+.
|
931
|
+
# - +:revert+ - Default is +false+.
|
813
932
|
def run(*migration_classes)
|
814
933
|
opts = migration_classes.extract_options!
|
815
934
|
dir = opts[:direction] || :up
|
@@ -846,7 +965,7 @@ module ActiveRecord
|
|
846
965
|
end
|
847
966
|
|
848
967
|
time = nil
|
849
|
-
ActiveRecord::
|
968
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection.pool.with_connection do |conn|
|
850
969
|
time = Benchmark.measure do
|
851
970
|
exec_migration(conn, direction)
|
852
971
|
end
|
@@ -871,6 +990,7 @@ module ActiveRecord
|
|
871
990
|
end
|
872
991
|
ensure
|
873
992
|
@connection = nil
|
993
|
+
@execution_strategy = nil
|
874
994
|
end
|
875
995
|
|
876
996
|
def write(text = "")
|
@@ -909,38 +1029,37 @@ module ActiveRecord
|
|
909
1029
|
end
|
910
1030
|
|
911
1031
|
def connection
|
912
|
-
@connection || ActiveRecord::
|
1032
|
+
@connection || ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
913
1033
|
end
|
914
1034
|
|
915
1035
|
def method_missing(method, *arguments, &block)
|
916
|
-
|
917
|
-
|
918
|
-
say_with_time "#{method}(#{arg_list})" do
|
1036
|
+
say_with_time "#{method}(#{format_arguments(arguments)})" do
|
919
1037
|
unless connection.respond_to? :revert
|
920
1038
|
unless arguments.empty? || [:execute, :enable_extension, :disable_extension].include?(method)
|
921
1039
|
arguments[0] = proper_table_name(arguments.first, table_name_options)
|
922
|
-
if
|
1040
|
+
if method == :rename_table ||
|
923
1041
|
(method == :remove_foreign_key && !arguments.second.is_a?(Hash))
|
924
1042
|
arguments[1] = proper_table_name(arguments.second, table_name_options)
|
925
1043
|
end
|
926
1044
|
end
|
927
1045
|
end
|
928
|
-
return super unless
|
929
|
-
|
1046
|
+
return super unless execution_strategy.respond_to?(method)
|
1047
|
+
execution_strategy.send(method, *arguments, &block)
|
930
1048
|
end
|
931
1049
|
end
|
932
|
-
ruby2_keywords(:method_missing)
|
1050
|
+
ruby2_keywords(:method_missing)
|
933
1051
|
|
934
1052
|
def copy(destination, sources, options = {})
|
935
1053
|
copied = []
|
936
|
-
schema_migration = options[:schema_migration] || ActiveRecord::SchemaMigration
|
937
1054
|
|
938
1055
|
FileUtils.mkdir_p(destination) unless File.exist?(destination)
|
1056
|
+
schema_migration = SchemaMigration::NullSchemaMigration.new
|
1057
|
+
internal_metadata = InternalMetadata::NullInternalMetadata.new
|
939
1058
|
|
940
|
-
destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration).migrations
|
1059
|
+
destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration, internal_metadata).migrations
|
941
1060
|
last = destination_migrations.last
|
942
1061
|
sources.each do |scope, path|
|
943
|
-
source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration).migrations
|
1062
|
+
source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration, internal_metadata).migrations
|
944
1063
|
|
945
1064
|
source_migrations.each do |migration|
|
946
1065
|
source = File.binread(migration.filename)
|
@@ -955,6 +1074,12 @@ module ActiveRecord
|
|
955
1074
|
magic_comments << magic_comment; ""
|
956
1075
|
end || break
|
957
1076
|
end
|
1077
|
+
|
1078
|
+
if !magic_comments.empty? && source.start_with?("\n")
|
1079
|
+
magic_comments << "\n"
|
1080
|
+
source = source[1..-1]
|
1081
|
+
end
|
1082
|
+
|
958
1083
|
source = "#{magic_comments}#{inserted_comment}#{source}"
|
959
1084
|
|
960
1085
|
if duplicate = destination_migrations.detect { |m| m.name == migration.name }
|
@@ -992,16 +1117,16 @@ module ActiveRecord
|
|
992
1117
|
|
993
1118
|
# Determines the version number of the next migration.
|
994
1119
|
def next_migration_number(number)
|
995
|
-
if ActiveRecord
|
1120
|
+
if ActiveRecord.timestamped_migrations
|
996
1121
|
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max
|
997
1122
|
else
|
998
|
-
|
1123
|
+
"%.3d" % number.to_i
|
999
1124
|
end
|
1000
1125
|
end
|
1001
1126
|
|
1002
1127
|
# Builds a hash for use in ActiveRecord::Migration#proper_table_name using
|
1003
1128
|
# the Active Record object's table_name prefix and suffix
|
1004
|
-
def table_name_options(config = ActiveRecord::Base)
|
1129
|
+
def table_name_options(config = ActiveRecord::Base) # :nodoc:
|
1005
1130
|
{
|
1006
1131
|
table_name_prefix: config.table_name_prefix,
|
1007
1132
|
table_name_suffix: config.table_name_suffix
|
@@ -1017,6 +1142,22 @@ module ActiveRecord
|
|
1017
1142
|
end
|
1018
1143
|
end
|
1019
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
|
+
|
1020
1161
|
def command_recorder
|
1021
1162
|
CommandRecorder.new(connection)
|
1022
1163
|
end
|
@@ -1042,19 +1183,66 @@ module ActiveRecord
|
|
1042
1183
|
end
|
1043
1184
|
|
1044
1185
|
def load_migration
|
1045
|
-
|
1186
|
+
Object.send(:remove_const, name) rescue nil
|
1187
|
+
|
1188
|
+
load(File.expand_path(filename))
|
1046
1189
|
name.constantize.new(name, version)
|
1047
1190
|
end
|
1048
1191
|
end
|
1049
1192
|
|
1050
|
-
|
1051
|
-
|
1193
|
+
# = \Migration \Context
|
1194
|
+
#
|
1195
|
+
# MigrationContext sets the context in which a migration is run.
|
1196
|
+
#
|
1197
|
+
# A migration context requires the path to the migrations is set
|
1198
|
+
# in the +migrations_paths+ parameter. Optionally a +schema_migration+
|
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.
|
1202
|
+
class MigrationContext
|
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
|
1052
1227
|
|
1053
|
-
def initialize(migrations_paths, schema_migration)
|
1054
1228
|
@migrations_paths = migrations_paths
|
1055
|
-
@schema_migration = schema_migration
|
1229
|
+
@schema_migration = schema_migration || SchemaMigration.new(connection)
|
1230
|
+
@internal_metadata = internal_metadata || InternalMetadata.new(connection)
|
1056
1231
|
end
|
1057
1232
|
|
1233
|
+
# Runs the migrations in the +migrations_path+.
|
1234
|
+
#
|
1235
|
+
# If +target_version+ is +nil+, +migrate+ will run +up+.
|
1236
|
+
#
|
1237
|
+
# If the +current_version+ and +target_version+ are both
|
1238
|
+
# 0 then an empty array will be returned and no migrations
|
1239
|
+
# will be run.
|
1240
|
+
#
|
1241
|
+
# If the +current_version+ in the schema is greater than
|
1242
|
+
# the +target_version+, then +down+ will be run.
|
1243
|
+
#
|
1244
|
+
# If none of the conditions are met, +up+ will be run with
|
1245
|
+
# the +target_version+.
|
1058
1246
|
def migrate(target_version = nil, &block)
|
1059
1247
|
case
|
1060
1248
|
when target_version.nil?
|
@@ -1068,64 +1256,64 @@ module ActiveRecord
|
|
1068
1256
|
end
|
1069
1257
|
end
|
1070
1258
|
|
1071
|
-
def rollback(steps = 1)
|
1259
|
+
def rollback(steps = 1) # :nodoc:
|
1072
1260
|
move(:down, steps)
|
1073
1261
|
end
|
1074
1262
|
|
1075
|
-
def forward(steps = 1)
|
1263
|
+
def forward(steps = 1) # :nodoc:
|
1076
1264
|
move(:up, steps)
|
1077
1265
|
end
|
1078
1266
|
|
1079
|
-
def up(target_version = nil)
|
1267
|
+
def up(target_version = nil, &block) # :nodoc:
|
1080
1268
|
selected_migrations = if block_given?
|
1081
|
-
migrations.select
|
1269
|
+
migrations.select(&block)
|
1082
1270
|
else
|
1083
1271
|
migrations
|
1084
1272
|
end
|
1085
1273
|
|
1086
|
-
Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate
|
1274
|
+
Migrator.new(:up, selected_migrations, schema_migration, internal_metadata, target_version).migrate
|
1087
1275
|
end
|
1088
1276
|
|
1089
|
-
def down(target_version = nil)
|
1277
|
+
def down(target_version = nil, &block) # :nodoc:
|
1090
1278
|
selected_migrations = if block_given?
|
1091
|
-
migrations.select
|
1279
|
+
migrations.select(&block)
|
1092
1280
|
else
|
1093
1281
|
migrations
|
1094
1282
|
end
|
1095
1283
|
|
1096
|
-
Migrator.new(:down, selected_migrations, schema_migration, target_version).migrate
|
1284
|
+
Migrator.new(:down, selected_migrations, schema_migration, internal_metadata, target_version).migrate
|
1097
1285
|
end
|
1098
1286
|
|
1099
|
-
def run(direction, target_version)
|
1100
|
-
Migrator.new(direction, migrations, schema_migration, target_version).run
|
1287
|
+
def run(direction, target_version) # :nodoc:
|
1288
|
+
Migrator.new(direction, migrations, schema_migration, internal_metadata, target_version).run
|
1101
1289
|
end
|
1102
1290
|
|
1103
|
-
def open
|
1104
|
-
Migrator.new(:up, migrations, schema_migration)
|
1291
|
+
def open # :nodoc:
|
1292
|
+
Migrator.new(:up, migrations, schema_migration, internal_metadata)
|
1105
1293
|
end
|
1106
1294
|
|
1107
|
-
def get_all_versions
|
1295
|
+
def get_all_versions # :nodoc:
|
1108
1296
|
if schema_migration.table_exists?
|
1109
|
-
schema_migration.
|
1297
|
+
schema_migration.integer_versions
|
1110
1298
|
else
|
1111
1299
|
[]
|
1112
1300
|
end
|
1113
1301
|
end
|
1114
1302
|
|
1115
|
-
def current_version
|
1303
|
+
def current_version # :nodoc:
|
1116
1304
|
get_all_versions.max || 0
|
1117
1305
|
rescue ActiveRecord::NoDatabaseError
|
1118
1306
|
end
|
1119
1307
|
|
1120
|
-
def needs_migration?
|
1121
|
-
|
1308
|
+
def needs_migration? # :nodoc:
|
1309
|
+
pending_migration_versions.size > 0
|
1122
1310
|
end
|
1123
1311
|
|
1124
|
-
def
|
1125
|
-
migrations.
|
1312
|
+
def pending_migration_versions # :nodoc:
|
1313
|
+
migrations.collect(&:version) - get_all_versions
|
1126
1314
|
end
|
1127
1315
|
|
1128
|
-
def migrations
|
1316
|
+
def migrations # :nodoc:
|
1129
1317
|
migrations = migration_files.map do |file|
|
1130
1318
|
version, name, scope = parse_migration_filename(file)
|
1131
1319
|
raise IllegalMigrationNameError.new(file) unless version
|
@@ -1138,43 +1326,47 @@ module ActiveRecord
|
|
1138
1326
|
migrations.sort_by(&:version)
|
1139
1327
|
end
|
1140
1328
|
|
1141
|
-
def migrations_status
|
1329
|
+
def migrations_status # :nodoc:
|
1142
1330
|
db_list = schema_migration.normalized_versions
|
1143
1331
|
|
1144
|
-
file_list = migration_files.
|
1332
|
+
file_list = migration_files.filter_map do |file|
|
1145
1333
|
version, name, scope = parse_migration_filename(file)
|
1146
1334
|
raise IllegalMigrationNameError.new(file) unless version
|
1147
1335
|
version = schema_migration.normalize_migration_number(version)
|
1148
1336
|
status = db_list.delete(version) ? "up" : "down"
|
1149
1337
|
[status, version, (name + scope).humanize]
|
1150
|
-
end
|
1338
|
+
end
|
1151
1339
|
|
1152
1340
|
db_list.map! do |version|
|
1153
1341
|
["up", version, "********** NO FILE **********"]
|
1154
1342
|
end
|
1155
1343
|
|
1156
|
-
(db_list + file_list).sort_by { |_, version, _| version }
|
1344
|
+
(db_list + file_list).sort_by { |_, version, _| version.to_i }
|
1157
1345
|
end
|
1158
1346
|
|
1159
|
-
def current_environment
|
1347
|
+
def current_environment # :nodoc:
|
1160
1348
|
ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
|
1161
1349
|
end
|
1162
1350
|
|
1163
|
-
def protected_environment?
|
1351
|
+
def protected_environment? # :nodoc:
|
1164
1352
|
ActiveRecord::Base.protected_environments.include?(last_stored_environment) if last_stored_environment
|
1165
1353
|
end
|
1166
1354
|
|
1167
|
-
def last_stored_environment
|
1168
|
-
return nil unless
|
1355
|
+
def last_stored_environment # :nodoc:
|
1356
|
+
return nil unless connection.internal_metadata.enabled?
|
1169
1357
|
return nil if current_version == 0
|
1170
|
-
raise NoEnvironmentInSchemaError unless
|
1358
|
+
raise NoEnvironmentInSchemaError unless connection.internal_metadata.table_exists?
|
1171
1359
|
|
1172
|
-
environment =
|
1360
|
+
environment = connection.internal_metadata[:environment]
|
1173
1361
|
raise NoEnvironmentInSchemaError unless environment
|
1174
1362
|
environment
|
1175
1363
|
end
|
1176
1364
|
|
1177
1365
|
private
|
1366
|
+
def connection
|
1367
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
1368
|
+
end
|
1369
|
+
|
1178
1370
|
def migration_files
|
1179
1371
|
paths = Array(migrations_paths)
|
1180
1372
|
Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
|
@@ -1185,7 +1377,7 @@ module ActiveRecord
|
|
1185
1377
|
end
|
1186
1378
|
|
1187
1379
|
def move(direction, steps)
|
1188
|
-
migrator = Migrator.new(direction, migrations, schema_migration)
|
1380
|
+
migrator = Migrator.new(direction, migrations, schema_migration, internal_metadata)
|
1189
1381
|
|
1190
1382
|
if current_version != 0 && !migrator.current_migration
|
1191
1383
|
raise UnknownMigrationVersionError.new(current_version)
|
@@ -1210,23 +1402,28 @@ module ActiveRecord
|
|
1210
1402
|
|
1211
1403
|
# For cases where a table doesn't exist like loading from schema cache
|
1212
1404
|
def current_version
|
1213
|
-
|
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
|
1214
1410
|
end
|
1215
1411
|
end
|
1216
1412
|
|
1217
1413
|
self.migrations_paths = ["db/migrate"]
|
1218
1414
|
|
1219
|
-
def initialize(direction, migrations, schema_migration, target_version = nil)
|
1415
|
+
def initialize(direction, migrations, schema_migration, internal_metadata, target_version = nil)
|
1220
1416
|
@direction = direction
|
1221
1417
|
@target_version = target_version
|
1222
1418
|
@migrated_versions = nil
|
1223
1419
|
@migrations = migrations
|
1224
1420
|
@schema_migration = schema_migration
|
1421
|
+
@internal_metadata = internal_metadata
|
1225
1422
|
|
1226
1423
|
validate(@migrations)
|
1227
1424
|
|
1228
1425
|
@schema_migration.create_table
|
1229
|
-
|
1426
|
+
@internal_metadata.create_table
|
1230
1427
|
end
|
1231
1428
|
|
1232
1429
|
def current_version
|
@@ -1279,18 +1476,21 @@ module ActiveRecord
|
|
1279
1476
|
end
|
1280
1477
|
|
1281
1478
|
def load_migrated
|
1282
|
-
@migrated_versions = Set.new(@schema_migration.
|
1479
|
+
@migrated_versions = Set.new(@schema_migration.integer_versions)
|
1283
1480
|
end
|
1284
1481
|
|
1285
1482
|
private
|
1483
|
+
def connection
|
1484
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
1485
|
+
end
|
1486
|
+
|
1286
1487
|
# Used for running a specific migration.
|
1287
1488
|
def run_without_lock
|
1288
1489
|
migration = migrations.detect { |m| m.version == @target_version }
|
1289
1490
|
raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
|
1290
|
-
result = execute_migration_in_transaction(migration)
|
1291
1491
|
|
1292
1492
|
record_environment
|
1293
|
-
|
1493
|
+
execute_migration_in_transaction(migration)
|
1294
1494
|
end
|
1295
1495
|
|
1296
1496
|
# Used for running multiple migrations up to or down to a certain value.
|
@@ -1299,15 +1499,15 @@ module ActiveRecord
|
|
1299
1499
|
raise UnknownMigrationVersionError.new(@target_version)
|
1300
1500
|
end
|
1301
1501
|
|
1302
|
-
result = runnable.each(&method(:execute_migration_in_transaction))
|
1303
1502
|
record_environment
|
1304
|
-
|
1503
|
+
runnable.each(&method(:execute_migration_in_transaction))
|
1305
1504
|
end
|
1306
1505
|
|
1307
1506
|
# Stores the current environment in the database.
|
1308
1507
|
def record_environment
|
1309
1508
|
return if down?
|
1310
|
-
|
1509
|
+
|
1510
|
+
@internal_metadata[:environment] = connection.pool.db_config.env_name
|
1311
1511
|
end
|
1312
1512
|
|
1313
1513
|
def ran?(migration)
|
@@ -1359,10 +1559,10 @@ module ActiveRecord
|
|
1359
1559
|
def record_version_state_after_migrating(version)
|
1360
1560
|
if down?
|
1361
1561
|
migrated.delete(version)
|
1362
|
-
@schema_migration.
|
1562
|
+
@schema_migration.delete_version(version.to_s)
|
1363
1563
|
else
|
1364
1564
|
migrated << version
|
1365
|
-
@schema_migration.
|
1565
|
+
@schema_migration.create_version(version.to_s)
|
1366
1566
|
end
|
1367
1567
|
end
|
1368
1568
|
|
@@ -1375,52 +1575,40 @@ module ActiveRecord
|
|
1375
1575
|
end
|
1376
1576
|
|
1377
1577
|
# Wrap the migration in a transaction only if supported by the adapter.
|
1378
|
-
def ddl_transaction(migration)
|
1578
|
+
def ddl_transaction(migration, &block)
|
1379
1579
|
if use_transaction?(migration)
|
1380
|
-
|
1580
|
+
connection.transaction(&block)
|
1381
1581
|
else
|
1382
1582
|
yield
|
1383
1583
|
end
|
1384
1584
|
end
|
1385
1585
|
|
1386
1586
|
def use_transaction?(migration)
|
1387
|
-
!migration.disable_ddl_transaction &&
|
1587
|
+
!migration.disable_ddl_transaction && connection.supports_ddl_transactions?
|
1388
1588
|
end
|
1389
1589
|
|
1390
1590
|
def use_advisory_lock?
|
1391
|
-
|
1591
|
+
connection.advisory_locks_enabled?
|
1392
1592
|
end
|
1393
1593
|
|
1394
1594
|
def with_advisory_lock
|
1395
1595
|
lock_id = generate_migrator_advisory_lock_id
|
1396
1596
|
|
1397
|
-
|
1398
|
-
|
1399
|
-
|
1400
|
-
|
1401
|
-
yield
|
1402
|
-
ensure
|
1403
|
-
if got_lock && !connection.release_advisory_lock(lock_id)
|
1404
|
-
raise ConcurrentMigrationError.new(
|
1405
|
-
ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
|
1406
|
-
)
|
1407
|
-
end
|
1408
|
-
end
|
1409
|
-
end
|
1410
|
-
|
1411
|
-
def with_advisory_lock_connection
|
1412
|
-
pool = ActiveRecord::ConnectionAdapters::ConnectionHandler.new.establish_connection(
|
1413
|
-
ActiveRecord::Base.connection_db_config
|
1414
|
-
)
|
1415
|
-
|
1416
|
-
pool.with_connection { |connection| yield(connection) }
|
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
|
1417
1601
|
ensure
|
1418
|
-
|
1602
|
+
if got_lock && !connection.release_advisory_lock(lock_id)
|
1603
|
+
raise ConcurrentMigrationError.new(
|
1604
|
+
ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
|
1605
|
+
)
|
1606
|
+
end
|
1419
1607
|
end
|
1420
1608
|
|
1421
1609
|
MIGRATOR_SALT = 2053462845
|
1422
1610
|
def generate_migrator_advisory_lock_id
|
1423
|
-
db_name_hash = Zlib.crc32(
|
1611
|
+
db_name_hash = Zlib.crc32(connection.current_database)
|
1424
1612
|
MIGRATOR_SALT * db_name_hash
|
1425
1613
|
end
|
1426
1614
|
end
|