activerecord 6.1.7 → 7.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +520 -1385
- data/MIT-LICENSE +1 -1
- data/README.rdoc +31 -31
- data/examples/performance.rb +2 -2
- data/lib/active_record/aggregations.rb +17 -14
- data/lib/active_record/association_relation.rb +2 -12
- data/lib/active_record/associations/alias_tracker.rb +25 -19
- data/lib/active_record/associations/association.rb +60 -21
- data/lib/active_record/associations/association_scope.rb +17 -12
- data/lib/active_record/associations/belongs_to_association.rb +37 -11
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -4
- data/lib/active_record/associations/builder/association.rb +11 -5
- data/lib/active_record/associations/builder/belongs_to.rb +41 -14
- data/lib/active_record/associations/builder/collection_association.rb +10 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -7
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +4 -4
- data/lib/active_record/associations/builder/singular_association.rb +6 -2
- data/lib/active_record/associations/collection_association.rb +46 -36
- data/lib/active_record/associations/collection_proxy.rb +44 -16
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/errors.rb +265 -0
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +29 -19
- 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 +27 -25
- data/lib/active_record/associations/join_dependency.rb +23 -15
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +212 -53
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +153 -0
- data/lib/active_record/associations/preloader/through_association.rb +50 -16
- data/lib/active_record/associations/preloader.rb +50 -121
- data/lib/active_record/associations/singular_association.rb +15 -3
- data/lib/active_record/associations/through_association.rb +25 -14
- data/lib/active_record/associations.rb +404 -509
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +2 -14
- data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +73 -22
- data/lib/active_record/attribute_methods/primary_key.rb +47 -27
- data/lib/active_record/attribute_methods/query.rb +31 -19
- data/lib/active_record/attribute_methods/read.rb +14 -11
- data/lib/active_record/attribute_methods/serialization.rb +174 -37
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +11 -9
- data/lib/active_record/attribute_methods/write.rb +12 -15
- data/lib/active_record/attribute_methods.rb +164 -52
- data/lib/active_record/attributes.rb +51 -49
- data/lib/active_record/autosave_association.rb +74 -57
- data/lib/active_record/base.rb +27 -5
- 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 +284 -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 +79 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +327 -612
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +199 -60
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +201 -64
- data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -131
- 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 +377 -142
- data/lib/active_record/connection_adapters/abstract/transaction.rb +361 -76
- data/lib/active_record/connection_adapters/abstract_adapter.rb +624 -163
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +345 -166
- 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 +29 -130
- data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -55
- 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 +45 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +107 -68
- data/lib/active_record/connection_adapters/pool_config.rb +26 -16
- 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 +114 -54
- 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/interval.rb +1 -1
- 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/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +137 -104
- 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 +173 -3
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +401 -77
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +518 -251
- data/lib/active_record/connection_adapters/schema_cache.rb +326 -102
- data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +78 -55
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +68 -54
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +20 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +66 -22
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +372 -130
- 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 +229 -0
- data/lib/active_record/connection_adapters.rb +130 -6
- data/lib/active_record/connection_handling.rb +132 -146
- data/lib/active_record/core.rb +276 -251
- data/lib/active_record/counter_cache.rb +68 -34
- data/lib/active_record/database_configurations/connection_url_resolver.rb +9 -3
- data/lib/active_record/database_configurations/database_config.rb +34 -10
- data/lib/active_record/database_configurations/hash_config.rb +107 -31
- data/lib/active_record/database_configurations/url_config.rb +38 -13
- data/lib/active_record/database_configurations.rb +96 -60
- data/lib/active_record/delegated_type.rb +90 -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 +3 -3
- 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 +175 -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 +170 -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_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +96 -0
- data/lib/active_record/encryption/null_encryptor.rb +25 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +28 -0
- data/lib/active_record/encryption/scheme.rb +100 -0
- data/lib/active_record/encryption.rb +56 -0
- data/lib/active_record/enum.rb +163 -63
- data/lib/active_record/errors.rb +210 -27
- data/lib/active_record/explain.rb +21 -12
- 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 +179 -112
- data/lib/active_record/future_result.rb +178 -0
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +85 -31
- data/lib/active_record/insert_all.rb +148 -32
- data/lib/active_record/integration.rb +14 -10
- data/lib/active_record/internal_metadata.rb +123 -23
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +43 -27
- data/lib/active_record/locking/pessimistic.rb +15 -6
- data/lib/active_record/log_subscriber.rb +41 -29
- data/lib/active_record/marshalling.rb +56 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +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 +113 -16
- data/lib/active_record/migration/compatibility.rb +235 -46
- data/lib/active_record/migration/default_strategy.rb +22 -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 +374 -177
- data/lib/active_record/model_schema.rb +143 -159
- data/lib/active_record/nested_attributes.rb +48 -21
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/normalization.rb +163 -0
- data/lib/active_record/persistence.rb +282 -283
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +19 -25
- data/lib/active_record/query_logs.rb +189 -0
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +44 -9
- data/lib/active_record/railtie.rb +234 -71
- data/lib/active_record/railties/controller_runtime.rb +25 -11
- data/lib/active_record/railties/databases.rake +189 -256
- 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 +325 -103
- data/lib/active_record/relation/batches/batch_enumerator.rb +38 -9
- data/lib/active_record/relation/batches.rb +198 -63
- data/lib/active_record/relation/calculations.rb +300 -111
- data/lib/active_record/relation/delegation.rb +33 -22
- data/lib/active_record/relation/finder_methods.rb +123 -52
- data/lib/active_record/relation/merger.rb +26 -19
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +38 -4
- 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 +29 -22
- data/lib/active_record/relation/query_attribute.rb +30 -12
- data/lib/active_record/relation/query_methods.rb +842 -150
- data/lib/active_record/relation/record_fetch_warning.rb +10 -9
- data/lib/active_record/relation/spawn_methods.rb +7 -6
- data/lib/active_record/relation/where_clause.rb +15 -36
- data/lib/active_record/relation.rb +736 -145
- data/lib/active_record/result.rb +67 -54
- data/lib/active_record/runtime_registry.rb +71 -13
- data/lib/active_record/sanitization.rb +84 -34
- data/lib/active_record/schema.rb +39 -23
- data/lib/active_record/schema_dumper.rb +90 -31
- data/lib/active_record/schema_migration.rb +74 -23
- 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 +30 -9
- data/lib/active_record/statement_cache.rb +7 -7
- data/lib/active_record/store.rb +10 -10
- data/lib/active_record/suppressor.rb +13 -15
- data/lib/active_record/table_metadata.rb +7 -3
- data/lib/active_record/tasks/database_tasks.rb +277 -149
- 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 +16 -7
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +173 -155
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +32 -19
- data/lib/active_record/token_for.rb +123 -0
- data/lib/active_record/touch_later.rb +12 -7
- data/lib/active_record/transaction.rb +132 -0
- data/lib/active_record/transactions.rb +118 -41
- data/lib/active_record/translation.rb +3 -5
- 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 -7
- 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/type_caster/connection.rb +4 -4
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +13 -7
- 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 +64 -15
- data/lib/active_record/validations.rb +12 -5
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +444 -32
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/collectors/bind.rb +2 -0
- data/lib/arel/collectors/composite.rb +7 -0
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +1 -1
- 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/binary.rb +6 -7
- data/lib/arel/nodes/bound_sql_literal.rb +65 -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/{and.rb → nary.rb} +9 -2
- data/lib/arel/nodes/node.rb +115 -5
- 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 +13 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes/update_statement.rb +8 -3
- data/lib/arel/nodes.rb +7 -2
- data/lib/arel/predications.rb +14 -4
- data/lib/arel/select_manager.rb +11 -5
- data/lib/arel/table.rb +9 -6
- data/lib/arel/tree_manager.rb +8 -15
- data/lib/arel/update_manager.rb +20 -5
- data/lib/arel/visitors/dot.rb +81 -90
- data/lib/arel/visitors/mysql.rb +23 -5
- data/lib/arel/visitors/postgresql.rb +1 -22
- data/lib/arel/visitors/to_sql.rb +170 -36
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +23 -4
- 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/templates/create_table_migration.rb.tt +4 -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 +100 -14
- 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.2]
|
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.2]
|
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.2]
|
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,63 @@ module ActiveRecord
|
|
130
131
|
end
|
131
132
|
end
|
132
133
|
|
133
|
-
class
|
134
|
+
class InvalidMigrationTimestampError < MigrationError # :nodoc:
|
135
|
+
def initialize(version = nil, name = nil)
|
136
|
+
if version && name
|
137
|
+
super(<<~MSG)
|
138
|
+
Invalid timestamp #{version} for migration file: #{name}.
|
139
|
+
Timestamp must be in form YYYYMMDDHHMMSS, and less than #{(Time.now.utc + 1.day).strftime("%Y%m%d%H%M%S")}.
|
140
|
+
MSG
|
141
|
+
else
|
142
|
+
super(<<~MSG)
|
143
|
+
Invalid timestamp for migration.
|
144
|
+
Timestamp must be in form YYYYMMDDHHMMSS, and less than #{(Time.now.utc + 1.day).strftime("%Y%m%d%H%M%S")}.
|
145
|
+
MSG
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
class PendingMigrationError < MigrationError # :nodoc:
|
134
151
|
include ActiveSupport::ActionableError
|
135
152
|
|
136
153
|
action "Run pending migrations" do
|
137
154
|
ActiveRecord::Tasks::DatabaseTasks.migrate
|
138
155
|
|
139
|
-
if ActiveRecord
|
140
|
-
ActiveRecord::Tasks::DatabaseTasks.
|
141
|
-
|
142
|
-
)
|
156
|
+
if ActiveRecord.dump_schema_after_migration
|
157
|
+
connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
158
|
+
ActiveRecord::Tasks::DatabaseTasks.dump_schema(connection.pool.db_config)
|
143
159
|
end
|
144
160
|
end
|
145
161
|
|
146
|
-
def initialize(message = nil)
|
147
|
-
|
162
|
+
def initialize(message = nil, pending_migrations: nil)
|
163
|
+
if pending_migrations.nil?
|
164
|
+
pending_migrations = connection_pool.migration_context.open.pending_migrations
|
165
|
+
end
|
166
|
+
|
167
|
+
super(message || detailed_migration_message(pending_migrations))
|
148
168
|
end
|
149
169
|
|
150
170
|
private
|
151
|
-
def detailed_migration_message
|
171
|
+
def detailed_migration_message(pending_migrations)
|
152
172
|
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)
|
173
|
+
message += " RAILS_ENV=#{::Rails.env}" if defined?(Rails.env) && !Rails.env.local?
|
154
174
|
message += "\n\n"
|
155
175
|
|
156
|
-
pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations
|
157
|
-
|
158
176
|
message += "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}\n\n"
|
159
177
|
|
160
178
|
pending_migrations.each do |pending_migration|
|
161
|
-
message += "#{pending_migration.
|
179
|
+
message += "#{pending_migration.filename}\n"
|
162
180
|
end
|
163
181
|
|
164
182
|
message
|
165
183
|
end
|
184
|
+
|
185
|
+
def connection_pool
|
186
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool
|
187
|
+
end
|
166
188
|
end
|
167
189
|
|
168
|
-
class ConcurrentMigrationError < MigrationError
|
190
|
+
class ConcurrentMigrationError < MigrationError # :nodoc:
|
169
191
|
DEFAULT_MESSAGE = "Cannot run migrations because another migration process is currently running."
|
170
192
|
RELEASE_LOCK_FAILED_MESSAGE = "Failed to release advisory lock"
|
171
193
|
|
@@ -174,7 +196,7 @@ module ActiveRecord
|
|
174
196
|
end
|
175
197
|
end
|
176
198
|
|
177
|
-
class NoEnvironmentInSchemaError < MigrationError
|
199
|
+
class NoEnvironmentInSchemaError < MigrationError # :nodoc:
|
178
200
|
def initialize
|
179
201
|
msg = "Environment data not found in the schema. To resolve this issue, run: \n\n bin/rails db:environment:set"
|
180
202
|
if defined?(Rails.env)
|
@@ -185,7 +207,7 @@ module ActiveRecord
|
|
185
207
|
end
|
186
208
|
end
|
187
209
|
|
188
|
-
class ProtectedEnvironmentError < ActiveRecordError
|
210
|
+
class ProtectedEnvironmentError < ActiveRecordError # :nodoc:
|
189
211
|
def initialize(env = "production")
|
190
212
|
msg = +"You are attempting to run a destructive action against your '#{env}' database.\n"
|
191
213
|
msg << "If you are sure you want to continue, run the same command with the environment variable:\n"
|
@@ -228,7 +250,7 @@ module ActiveRecord
|
|
228
250
|
#
|
229
251
|
# Example of a simple migration:
|
230
252
|
#
|
231
|
-
# class AddSsl < ActiveRecord::Migration[
|
253
|
+
# class AddSsl < ActiveRecord::Migration[7.2]
|
232
254
|
# def up
|
233
255
|
# add_column :accounts, :ssl_enabled, :boolean, default: true
|
234
256
|
# end
|
@@ -248,7 +270,7 @@ module ActiveRecord
|
|
248
270
|
#
|
249
271
|
# Example of a more complex migration that also needs to initialize data:
|
250
272
|
#
|
251
|
-
# class AddSystemSettings < ActiveRecord::Migration[
|
273
|
+
# class AddSystemSettings < ActiveRecord::Migration[7.2]
|
252
274
|
# def up
|
253
275
|
# create_table :system_settings do |t|
|
254
276
|
# t.string :name
|
@@ -326,7 +348,7 @@ module ActiveRecord
|
|
326
348
|
# details.
|
327
349
|
# * <tt>change_table(name, options)</tt>: Allows to make column alterations to
|
328
350
|
# 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.
|
351
|
+
# can then add/remove columns, indexes, or foreign keys to it.
|
330
352
|
# * <tt>rename_column(table_name, column_name, new_column_name)</tt>: Renames
|
331
353
|
# a column but keeps the type and content.
|
332
354
|
# * <tt>rename_index(table_name, old_name, new_name)</tt>: Renames an index.
|
@@ -356,15 +378,16 @@ module ActiveRecord
|
|
356
378
|
# == Irreversible transformations
|
357
379
|
#
|
358
380
|
# Some transformations are destructive in a manner that cannot be reversed.
|
359
|
-
# Migrations of that kind should raise an
|
381
|
+
# Migrations of that kind should raise an ActiveRecord::IrreversibleMigration
|
360
382
|
# exception in their +down+ method.
|
361
383
|
#
|
362
|
-
# == Running migrations from within Rails
|
384
|
+
# == Running migrations from within \Rails
|
363
385
|
#
|
364
|
-
# The Rails package has several tools to help create and apply migrations.
|
386
|
+
# The \Rails package has several tools to help create and apply migrations.
|
365
387
|
#
|
366
388
|
# To generate a new migration, you can use
|
367
|
-
#
|
389
|
+
#
|
390
|
+
# $ bin/rails generate migration MyNewMigration
|
368
391
|
#
|
369
392
|
# where MyNewMigration is the name of your migration. The generator will
|
370
393
|
# create an empty migration file <tt>timestamp_my_new_migration.rb</tt>
|
@@ -373,10 +396,10 @@ module ActiveRecord
|
|
373
396
|
#
|
374
397
|
# There is a special syntactic shortcut to generate migrations that add fields to a table.
|
375
398
|
#
|
376
|
-
# bin/rails generate migration add_fieldname_to_tablename fieldname:string
|
399
|
+
# $ bin/rails generate migration add_fieldname_to_tablename fieldname:string
|
377
400
|
#
|
378
401
|
# This will generate the file <tt>timestamp_add_fieldname_to_tablename.rb</tt>, which will look like this:
|
379
|
-
# class AddFieldnameToTablename < ActiveRecord::Migration[
|
402
|
+
# class AddFieldnameToTablename < ActiveRecord::Migration[7.2]
|
380
403
|
# def change
|
381
404
|
# add_column :tablenames, :fieldname, :string
|
382
405
|
# end
|
@@ -395,14 +418,14 @@ module ActiveRecord
|
|
395
418
|
# wish to rollback last few migrations. <tt>bin/rails db:rollback STEP=2</tt> will rollback
|
396
419
|
# the latest two migrations.
|
397
420
|
#
|
398
|
-
# If any of the migrations throw an
|
421
|
+
# If any of the migrations throw an ActiveRecord::IrreversibleMigration exception,
|
399
422
|
# that step will fail and you'll have some manual work to do.
|
400
423
|
#
|
401
424
|
# == More examples
|
402
425
|
#
|
403
426
|
# Not all migrations change the schema. Some just fix the data:
|
404
427
|
#
|
405
|
-
# class RemoveEmptyTags < ActiveRecord::Migration[
|
428
|
+
# class RemoveEmptyTags < ActiveRecord::Migration[7.2]
|
406
429
|
# def up
|
407
430
|
# Tag.all.each { |tag| tag.destroy if tag.pages.empty? }
|
408
431
|
# end
|
@@ -415,7 +438,7 @@ module ActiveRecord
|
|
415
438
|
#
|
416
439
|
# Others remove columns when they migrate up instead of down:
|
417
440
|
#
|
418
|
-
# class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[
|
441
|
+
# class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[7.2]
|
419
442
|
# def up
|
420
443
|
# remove_column :items, :incomplete_items_count
|
421
444
|
# remove_column :items, :completed_items_count
|
@@ -429,7 +452,7 @@ module ActiveRecord
|
|
429
452
|
#
|
430
453
|
# And sometimes you need to do something in SQL not abstracted directly by migrations:
|
431
454
|
#
|
432
|
-
# class MakeJoinUnique < ActiveRecord::Migration[
|
455
|
+
# class MakeJoinUnique < ActiveRecord::Migration[7.2]
|
433
456
|
# def up
|
434
457
|
# execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)"
|
435
458
|
# end
|
@@ -446,7 +469,7 @@ module ActiveRecord
|
|
446
469
|
# <tt>Base#reset_column_information</tt> in order to ensure that the model has the
|
447
470
|
# latest column data from after the new column was added. Example:
|
448
471
|
#
|
449
|
-
# class AddPeopleSalary < ActiveRecord::Migration[
|
472
|
+
# class AddPeopleSalary < ActiveRecord::Migration[7.2]
|
450
473
|
# def up
|
451
474
|
# add_column :people, :salary, :integer
|
452
475
|
# Person.reset_column_information
|
@@ -462,7 +485,7 @@ module ActiveRecord
|
|
462
485
|
# them to the console as they happen, along with benchmarks describing how
|
463
486
|
# long each step took.
|
464
487
|
#
|
465
|
-
# You can quiet them down by setting ActiveRecord::Migration.verbose = false
|
488
|
+
# You can quiet them down by setting <tt>ActiveRecord::Migration.verbose = false</tt>.
|
466
489
|
#
|
467
490
|
# You can also insert your own messages and benchmarks by using the +say_with_time+
|
468
491
|
# method:
|
@@ -482,11 +505,15 @@ module ActiveRecord
|
|
482
505
|
#
|
483
506
|
# == Timestamped Migrations
|
484
507
|
#
|
485
|
-
# By default, Rails generates migrations that look like:
|
508
|
+
# By default, \Rails generates migrations that look like:
|
486
509
|
#
|
487
510
|
# 20080717013526_your_migration_name.rb
|
488
511
|
#
|
489
|
-
# The prefix is a generation timestamp (in UTC).
|
512
|
+
# The prefix is a generation timestamp (in UTC). Timestamps should not be
|
513
|
+
# modified manually. To validate that migration timestamps adhere to the
|
514
|
+
# format Active Record expects, you can use the following configuration option:
|
515
|
+
#
|
516
|
+
# config.active_record.validate_migration_timestamps = true
|
490
517
|
#
|
491
518
|
# If you'd prefer to use numeric prefixes, you can turn timestamped migrations
|
492
519
|
# off by setting:
|
@@ -504,7 +531,7 @@ module ActiveRecord
|
|
504
531
|
# To define a reversible migration, define the +change+ method in your
|
505
532
|
# migration like this:
|
506
533
|
#
|
507
|
-
# class TenderloveMigration < ActiveRecord::Migration[
|
534
|
+
# class TenderloveMigration < ActiveRecord::Migration[7.2]
|
508
535
|
# def change
|
509
536
|
# create_table(:horses) do |t|
|
510
537
|
# t.column :content, :text
|
@@ -521,11 +548,11 @@ module ActiveRecord
|
|
521
548
|
# as before.
|
522
549
|
#
|
523
550
|
# If a command cannot be reversed, an
|
524
|
-
#
|
551
|
+
# ActiveRecord::IrreversibleMigration exception will be raised when
|
525
552
|
# the migration is moving down.
|
526
553
|
#
|
527
554
|
# For a list of commands that are reversible, please see
|
528
|
-
#
|
555
|
+
# +ActiveRecord::Migration::CommandRecorder+.
|
529
556
|
#
|
530
557
|
# == Transactional Migrations
|
531
558
|
#
|
@@ -534,7 +561,7 @@ module ActiveRecord
|
|
534
561
|
# can't execute inside a transaction though, and for these situations
|
535
562
|
# you can turn the automatic transactions off.
|
536
563
|
#
|
537
|
-
# class ChangeEnum < ActiveRecord::Migration[
|
564
|
+
# class ChangeEnum < ActiveRecord::Migration[7.2]
|
538
565
|
# disable_ddl_transaction!
|
539
566
|
#
|
540
567
|
# def up
|
@@ -548,18 +575,57 @@ module ActiveRecord
|
|
548
575
|
autoload :CommandRecorder, "active_record/migration/command_recorder"
|
549
576
|
autoload :Compatibility, "active_record/migration/compatibility"
|
550
577
|
autoload :JoinTable, "active_record/migration/join_table"
|
578
|
+
autoload :ExecutionStrategy, "active_record/migration/execution_strategy"
|
579
|
+
autoload :DefaultStrategy, "active_record/migration/default_strategy"
|
551
580
|
|
552
581
|
# This must be defined before the inherited hook, below
|
553
|
-
class Current < Migration
|
582
|
+
class Current < Migration # :nodoc:
|
583
|
+
def create_table(table_name, **options)
|
584
|
+
if block_given?
|
585
|
+
super { |t| yield compatible_table_definition(t) }
|
586
|
+
else
|
587
|
+
super
|
588
|
+
end
|
589
|
+
end
|
590
|
+
|
591
|
+
def change_table(table_name, **options)
|
592
|
+
if block_given?
|
593
|
+
super { |t| yield compatible_table_definition(t) }
|
594
|
+
else
|
595
|
+
super
|
596
|
+
end
|
597
|
+
end
|
598
|
+
|
599
|
+
def create_join_table(table_1, table_2, **options)
|
600
|
+
if block_given?
|
601
|
+
super { |t| yield compatible_table_definition(t) }
|
602
|
+
else
|
603
|
+
super
|
604
|
+
end
|
605
|
+
end
|
606
|
+
|
607
|
+
def drop_table(table_name, **options)
|
608
|
+
if block_given?
|
609
|
+
super { |t| yield compatible_table_definition(t) }
|
610
|
+
else
|
611
|
+
super
|
612
|
+
end
|
613
|
+
end
|
614
|
+
|
615
|
+
def compatible_table_definition(t)
|
616
|
+
t
|
617
|
+
end
|
554
618
|
end
|
555
619
|
|
556
|
-
def self.inherited(subclass)
|
620
|
+
def self.inherited(subclass) # :nodoc:
|
557
621
|
super
|
558
622
|
if subclass.superclass == Migration
|
623
|
+
major = ActiveRecord::VERSION::MAJOR
|
624
|
+
minor = ActiveRecord::VERSION::MINOR
|
559
625
|
raise StandardError, "Directly inheriting from ActiveRecord::Migration is not supported. " \
|
560
|
-
"Please specify the
|
626
|
+
"Please specify the Active Record release the migration was written for:\n" \
|
561
627
|
"\n" \
|
562
|
-
" class #{subclass} < ActiveRecord::Migration[
|
628
|
+
" class #{subclass} < ActiveRecord::Migration[#{major}.#{minor}]"
|
563
629
|
end
|
564
630
|
end
|
565
631
|
|
@@ -571,10 +637,17 @@ module ActiveRecord
|
|
571
637
|
ActiveRecord::VERSION::STRING.to_f
|
572
638
|
end
|
573
639
|
|
574
|
-
MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/
|
640
|
+
MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/ # :nodoc:
|
641
|
+
|
642
|
+
def self.valid_version_format?(version_string) # :nodoc:
|
643
|
+
[
|
644
|
+
MigrationFilenameRegexp,
|
645
|
+
/\A\d(_?\d)*\z/ # integer with optional underscores
|
646
|
+
].any? { |pattern| pattern.match?(version_string) }
|
647
|
+
end
|
575
648
|
|
576
649
|
# 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
|
650
|
+
# loading a web page if <tt>config.active_record.migration_error</tt> is set to +:page_load+.
|
578
651
|
class CheckPending
|
579
652
|
def initialize(app, file_watcher: ActiveSupport::FileUpdateChecker)
|
580
653
|
@app = app
|
@@ -587,7 +660,7 @@ module ActiveRecord
|
|
587
660
|
@mutex.synchronize do
|
588
661
|
@watcher ||= build_watcher do
|
589
662
|
@needs_check = true
|
590
|
-
ActiveRecord::Migration.
|
663
|
+
ActiveRecord::Migration.check_pending_migrations
|
591
664
|
@needs_check = false
|
592
665
|
end
|
593
666
|
|
@@ -603,61 +676,66 @@ module ActiveRecord
|
|
603
676
|
|
604
677
|
private
|
605
678
|
def build_watcher(&block)
|
606
|
-
|
679
|
+
current_environment = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
|
680
|
+
all_configs = ActiveRecord::Base.configurations.configs_for(env_name: current_environment)
|
681
|
+
paths = all_configs.flat_map { |config| config.migrations_paths || Migrator.migrations_paths }.uniq
|
607
682
|
@file_watcher.new([], paths.index_with(["rb"]), &block)
|
608
683
|
end
|
609
684
|
|
610
685
|
def connection
|
611
|
-
ActiveRecord::
|
686
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
612
687
|
end
|
613
688
|
end
|
614
689
|
|
615
690
|
class << self
|
616
|
-
attr_accessor :delegate
|
617
|
-
attr_accessor :disable_ddl_transaction
|
691
|
+
attr_accessor :delegate # :nodoc:
|
692
|
+
attr_accessor :disable_ddl_transaction # :nodoc:
|
618
693
|
|
619
|
-
def nearest_delegate
|
694
|
+
def nearest_delegate # :nodoc:
|
620
695
|
delegate || superclass.nearest_delegate
|
621
696
|
end
|
622
697
|
|
623
|
-
# Raises
|
624
|
-
|
625
|
-
|
626
|
-
|
698
|
+
# Raises ActiveRecord::PendingMigrationError error if any migrations are pending
|
699
|
+
# for all database configurations in an environment.
|
700
|
+
def check_all_pending!
|
701
|
+
pending_migrations = []
|
627
702
|
|
628
|
-
|
629
|
-
|
630
|
-
|
703
|
+
ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: env) do |pool|
|
704
|
+
if pending = pool.migration_context.open.pending_migrations
|
705
|
+
pending_migrations << pending
|
706
|
+
end
|
707
|
+
end
|
708
|
+
|
709
|
+
migrations = pending_migrations.flatten
|
631
710
|
|
632
|
-
|
633
|
-
|
711
|
+
if migrations.any?
|
712
|
+
raise ActiveRecord::PendingMigrationError.new(pending_migrations: migrations)
|
634
713
|
end
|
714
|
+
end
|
635
715
|
|
636
|
-
|
716
|
+
def load_schema_if_pending!
|
717
|
+
if any_schema_needs_update?
|
637
718
|
# Roundtrip to Rake to allow plugins to hook into database initialization.
|
638
719
|
root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
|
720
|
+
|
639
721
|
FileUtils.cd(root) do
|
640
|
-
Base.clear_all_connections!
|
722
|
+
Base.connection_handler.clear_all_connections!(:all)
|
641
723
|
system("bin/rails db:test:prepare")
|
642
724
|
end
|
643
725
|
end
|
644
726
|
|
645
|
-
|
646
|
-
Base.establish_connection(current_db_config)
|
647
|
-
|
648
|
-
check_pending!
|
727
|
+
check_pending_migrations
|
649
728
|
end
|
650
729
|
|
651
|
-
def maintain_test_schema!
|
652
|
-
if ActiveRecord
|
730
|
+
def maintain_test_schema! # :nodoc:
|
731
|
+
if ActiveRecord.maintain_test_schema
|
653
732
|
suppress_messages { load_schema_if_pending! }
|
654
733
|
end
|
655
734
|
end
|
656
735
|
|
657
|
-
def method_missing(name,
|
658
|
-
nearest_delegate.send(name,
|
736
|
+
def method_missing(name, ...) # :nodoc:
|
737
|
+
nearest_delegate.send(name, ...)
|
659
738
|
end
|
660
|
-
ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
|
661
739
|
|
662
740
|
def migrate(direction)
|
663
741
|
new.migrate direction
|
@@ -670,12 +748,55 @@ module ActiveRecord
|
|
670
748
|
def disable_ddl_transaction!
|
671
749
|
@disable_ddl_transaction = true
|
672
750
|
end
|
751
|
+
|
752
|
+
def check_pending_migrations # :nodoc:
|
753
|
+
migrations = pending_migrations
|
754
|
+
|
755
|
+
if migrations.any?
|
756
|
+
raise ActiveRecord::PendingMigrationError.new(pending_migrations: migrations)
|
757
|
+
end
|
758
|
+
end
|
759
|
+
|
760
|
+
private
|
761
|
+
def any_schema_needs_update?
|
762
|
+
!db_configs_in_current_env.all? do |db_config|
|
763
|
+
Tasks::DatabaseTasks.schema_up_to_date?(db_config, ActiveRecord.schema_format)
|
764
|
+
end
|
765
|
+
end
|
766
|
+
|
767
|
+
def db_configs_in_current_env
|
768
|
+
ActiveRecord::Base.configurations.configs_for(env_name: env)
|
769
|
+
end
|
770
|
+
|
771
|
+
def pending_migrations
|
772
|
+
pending_migrations = []
|
773
|
+
|
774
|
+
ActiveRecord::Base.configurations.configs_for(env_name: env).each do |db_config|
|
775
|
+
ActiveRecord::PendingMigrationConnection.with_temporary_pool(db_config) do |pool|
|
776
|
+
if pending = pool.migration_context.open.pending_migrations
|
777
|
+
pending_migrations << pending
|
778
|
+
end
|
779
|
+
end
|
780
|
+
end
|
781
|
+
|
782
|
+
pending_migrations.flatten
|
783
|
+
end
|
784
|
+
|
785
|
+
def env
|
786
|
+
ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
|
787
|
+
end
|
673
788
|
end
|
674
789
|
|
675
|
-
def disable_ddl_transaction
|
790
|
+
def disable_ddl_transaction # :nodoc:
|
676
791
|
self.class.disable_ddl_transaction
|
677
792
|
end
|
678
793
|
|
794
|
+
##
|
795
|
+
# :singleton-method: verbose
|
796
|
+
#
|
797
|
+
# Specifies if migrations will write the actions they are taking to the console as they
|
798
|
+
# happen, along with benchmarks describing how long each step took. Defaults to
|
799
|
+
# true.
|
679
800
|
cattr_accessor :verbose
|
680
801
|
attr_accessor :name, :version
|
681
802
|
|
@@ -683,6 +804,11 @@ module ActiveRecord
|
|
683
804
|
@name = name
|
684
805
|
@version = version
|
685
806
|
@connection = nil
|
807
|
+
@pool = nil
|
808
|
+
end
|
809
|
+
|
810
|
+
def execution_strategy
|
811
|
+
@execution_strategy ||= ActiveRecord.migration_strategy.new(self)
|
686
812
|
end
|
687
813
|
|
688
814
|
self.verbose = true
|
@@ -696,7 +822,7 @@ module ActiveRecord
|
|
696
822
|
# and create the table 'apples' on the way up, and the reverse
|
697
823
|
# on the way down.
|
698
824
|
#
|
699
|
-
# class FixTLMigration < ActiveRecord::Migration[
|
825
|
+
# class FixTLMigration < ActiveRecord::Migration[7.2]
|
700
826
|
# def change
|
701
827
|
# revert do
|
702
828
|
# create_table(:horses) do |t|
|
@@ -715,7 +841,7 @@ module ActiveRecord
|
|
715
841
|
#
|
716
842
|
# require_relative "20121212123456_tenderlove_migration"
|
717
843
|
#
|
718
|
-
# class FixupTLMigration < ActiveRecord::Migration[
|
844
|
+
# class FixupTLMigration < ActiveRecord::Migration[7.2]
|
719
845
|
# def change
|
720
846
|
# revert TenderloveMigration
|
721
847
|
#
|
@@ -726,16 +852,16 @@ module ActiveRecord
|
|
726
852
|
# end
|
727
853
|
#
|
728
854
|
# This command can be nested.
|
729
|
-
def revert(*migration_classes)
|
855
|
+
def revert(*migration_classes, &block)
|
730
856
|
run(*migration_classes.reverse, revert: true) unless migration_classes.empty?
|
731
857
|
if block_given?
|
732
858
|
if connection.respond_to? :revert
|
733
|
-
connection.revert
|
859
|
+
connection.revert(&block)
|
734
860
|
else
|
735
861
|
recorder = command_recorder
|
736
862
|
@connection = recorder
|
737
863
|
suppress_messages do
|
738
|
-
connection.revert
|
864
|
+
connection.revert(&block)
|
739
865
|
end
|
740
866
|
@connection = recorder.delegate
|
741
867
|
recorder.replay(self)
|
@@ -747,7 +873,7 @@ module ActiveRecord
|
|
747
873
|
connection.respond_to?(:reverting) && connection.reverting
|
748
874
|
end
|
749
875
|
|
750
|
-
ReversibleBlockHelper = Struct.new(:reverting) do
|
876
|
+
ReversibleBlockHelper = Struct.new(:reverting) do # :nodoc:
|
751
877
|
def up
|
752
878
|
yield unless reverting
|
753
879
|
end
|
@@ -766,7 +892,7 @@ module ActiveRecord
|
|
766
892
|
# when the three columns 'first_name', 'last_name' and 'full_name' exist,
|
767
893
|
# even when migrating down:
|
768
894
|
#
|
769
|
-
# class SplitNameMigration < ActiveRecord::Migration[
|
895
|
+
# class SplitNameMigration < ActiveRecord::Migration[7.2]
|
770
896
|
# def change
|
771
897
|
# add_column :users, :first_name, :string
|
772
898
|
# add_column :users, :last_name, :string
|
@@ -794,7 +920,7 @@ module ActiveRecord
|
|
794
920
|
# In the following example, the new column +published+ will be given
|
795
921
|
# the value +true+ for all existing records.
|
796
922
|
#
|
797
|
-
# class AddPublishedToPosts < ActiveRecord::Migration[
|
923
|
+
# class AddPublishedToPosts < ActiveRecord::Migration[7.2]
|
798
924
|
# def change
|
799
925
|
# add_column :posts, :published, :boolean, default: false
|
800
926
|
# up_only do
|
@@ -802,14 +928,15 @@ module ActiveRecord
|
|
802
928
|
# end
|
803
929
|
# end
|
804
930
|
# end
|
805
|
-
def up_only
|
806
|
-
execute_block
|
931
|
+
def up_only(&block)
|
932
|
+
execute_block(&block) unless reverting?
|
807
933
|
end
|
808
934
|
|
809
935
|
# Runs the given migration classes.
|
810
936
|
# Last argument can specify options:
|
811
|
-
#
|
812
|
-
# -
|
937
|
+
#
|
938
|
+
# - +:direction+ - Default is +:up+.
|
939
|
+
# - +:revert+ - Default is +false+.
|
813
940
|
def run(*migration_classes)
|
814
941
|
opts = migration_classes.extract_options!
|
815
942
|
dir = opts[:direction] || :up
|
@@ -846,7 +973,7 @@ module ActiveRecord
|
|
846
973
|
end
|
847
974
|
|
848
975
|
time = nil
|
849
|
-
ActiveRecord::
|
976
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection.pool.with_connection do |conn|
|
850
977
|
time = Benchmark.measure do
|
851
978
|
exec_migration(conn, direction)
|
852
979
|
end
|
@@ -871,6 +998,7 @@ module ActiveRecord
|
|
871
998
|
end
|
872
999
|
ensure
|
873
1000
|
@connection = nil
|
1001
|
+
@execution_strategy = nil
|
874
1002
|
end
|
875
1003
|
|
876
1004
|
def write(text = "")
|
@@ -909,38 +1037,41 @@ module ActiveRecord
|
|
909
1037
|
end
|
910
1038
|
|
911
1039
|
def connection
|
912
|
-
@connection || ActiveRecord::
|
1040
|
+
@connection || ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
913
1041
|
end
|
914
1042
|
|
915
|
-
def
|
916
|
-
|
1043
|
+
def connection_pool
|
1044
|
+
@pool || ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool
|
1045
|
+
end
|
917
1046
|
|
918
|
-
|
1047
|
+
def method_missing(method, *arguments, &block)
|
1048
|
+
say_with_time "#{method}(#{format_arguments(arguments)})" do
|
919
1049
|
unless connection.respond_to? :revert
|
920
1050
|
unless arguments.empty? || [:execute, :enable_extension, :disable_extension].include?(method)
|
921
1051
|
arguments[0] = proper_table_name(arguments.first, table_name_options)
|
922
|
-
if
|
1052
|
+
if method == :rename_table ||
|
923
1053
|
(method == :remove_foreign_key && !arguments.second.is_a?(Hash))
|
924
1054
|
arguments[1] = proper_table_name(arguments.second, table_name_options)
|
925
1055
|
end
|
926
1056
|
end
|
927
1057
|
end
|
928
|
-
return super unless
|
929
|
-
|
1058
|
+
return super unless execution_strategy.respond_to?(method)
|
1059
|
+
execution_strategy.send(method, *arguments, &block)
|
930
1060
|
end
|
931
1061
|
end
|
932
|
-
ruby2_keywords(:method_missing)
|
1062
|
+
ruby2_keywords(:method_missing)
|
933
1063
|
|
934
1064
|
def copy(destination, sources, options = {})
|
935
1065
|
copied = []
|
936
|
-
schema_migration = options[:schema_migration] || ActiveRecord::SchemaMigration
|
937
1066
|
|
938
1067
|
FileUtils.mkdir_p(destination) unless File.exist?(destination)
|
1068
|
+
schema_migration = SchemaMigration::NullSchemaMigration.new
|
1069
|
+
internal_metadata = InternalMetadata::NullInternalMetadata.new
|
939
1070
|
|
940
|
-
destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration).migrations
|
1071
|
+
destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration, internal_metadata).migrations
|
941
1072
|
last = destination_migrations.last
|
942
1073
|
sources.each do |scope, path|
|
943
|
-
source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration).migrations
|
1074
|
+
source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration, internal_metadata).migrations
|
944
1075
|
|
945
1076
|
source_migrations.each do |migration|
|
946
1077
|
source = File.binread(migration.filename)
|
@@ -955,6 +1086,12 @@ module ActiveRecord
|
|
955
1086
|
magic_comments << magic_comment; ""
|
956
1087
|
end || break
|
957
1088
|
end
|
1089
|
+
|
1090
|
+
if !magic_comments.empty? && source.start_with?("\n")
|
1091
|
+
magic_comments << "\n"
|
1092
|
+
source = source[1..-1]
|
1093
|
+
end
|
1094
|
+
|
958
1095
|
source = "#{magic_comments}#{inserted_comment}#{source}"
|
959
1096
|
|
960
1097
|
if duplicate = destination_migrations.detect { |m| m.name == migration.name }
|
@@ -992,16 +1129,16 @@ module ActiveRecord
|
|
992
1129
|
|
993
1130
|
# Determines the version number of the next migration.
|
994
1131
|
def next_migration_number(number)
|
995
|
-
if ActiveRecord
|
1132
|
+
if ActiveRecord.timestamped_migrations
|
996
1133
|
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max
|
997
1134
|
else
|
998
|
-
|
1135
|
+
"%.3d" % number.to_i
|
999
1136
|
end
|
1000
1137
|
end
|
1001
1138
|
|
1002
1139
|
# Builds a hash for use in ActiveRecord::Migration#proper_table_name using
|
1003
1140
|
# the Active Record object's table_name prefix and suffix
|
1004
|
-
def table_name_options(config = ActiveRecord::Base)
|
1141
|
+
def table_name_options(config = ActiveRecord::Base) # :nodoc:
|
1005
1142
|
{
|
1006
1143
|
table_name_prefix: config.table_name_prefix,
|
1007
1144
|
table_name_suffix: config.table_name_suffix
|
@@ -1017,6 +1154,22 @@ module ActiveRecord
|
|
1017
1154
|
end
|
1018
1155
|
end
|
1019
1156
|
|
1157
|
+
def format_arguments(arguments)
|
1158
|
+
arg_list = arguments[0...-1].map(&:inspect)
|
1159
|
+
last_arg = arguments.last
|
1160
|
+
if last_arg.is_a?(Hash)
|
1161
|
+
last_arg = last_arg.reject { |k, _v| internal_option?(k) }
|
1162
|
+
arg_list << last_arg.inspect unless last_arg.empty?
|
1163
|
+
else
|
1164
|
+
arg_list << last_arg.inspect
|
1165
|
+
end
|
1166
|
+
arg_list.join(", ")
|
1167
|
+
end
|
1168
|
+
|
1169
|
+
def internal_option?(option_name)
|
1170
|
+
option_name.start_with?("_")
|
1171
|
+
end
|
1172
|
+
|
1020
1173
|
def command_recorder
|
1021
1174
|
CommandRecorder.new(connection)
|
1022
1175
|
end
|
@@ -1042,19 +1195,44 @@ module ActiveRecord
|
|
1042
1195
|
end
|
1043
1196
|
|
1044
1197
|
def load_migration
|
1045
|
-
|
1198
|
+
Object.send(:remove_const, name) rescue nil
|
1199
|
+
|
1200
|
+
load(File.expand_path(filename))
|
1046
1201
|
name.constantize.new(name, version)
|
1047
1202
|
end
|
1048
1203
|
end
|
1049
1204
|
|
1050
|
-
|
1051
|
-
|
1205
|
+
# = \Migration \Context
|
1206
|
+
#
|
1207
|
+
# MigrationContext sets the context in which a migration is run.
|
1208
|
+
#
|
1209
|
+
# A migration context requires the path to the migrations is set
|
1210
|
+
# in the +migrations_paths+ parameter. Optionally a +schema_migration+
|
1211
|
+
# class can be provided. Multiple database applications will instantiate
|
1212
|
+
# a +SchemaMigration+ object per database. From the Rake tasks, \Rails will
|
1213
|
+
# handle this for you.
|
1214
|
+
class MigrationContext
|
1215
|
+
attr_reader :migrations_paths, :schema_migration, :internal_metadata
|
1052
1216
|
|
1053
|
-
def initialize(migrations_paths, schema_migration)
|
1217
|
+
def initialize(migrations_paths, schema_migration = nil, internal_metadata = nil)
|
1054
1218
|
@migrations_paths = migrations_paths
|
1055
|
-
@schema_migration = schema_migration
|
1219
|
+
@schema_migration = schema_migration || SchemaMigration.new(connection_pool)
|
1220
|
+
@internal_metadata = internal_metadata || InternalMetadata.new(connection_pool)
|
1056
1221
|
end
|
1057
1222
|
|
1223
|
+
# Runs the migrations in the +migrations_path+.
|
1224
|
+
#
|
1225
|
+
# If +target_version+ is +nil+, +migrate+ will run +up+.
|
1226
|
+
#
|
1227
|
+
# If the +current_version+ and +target_version+ are both
|
1228
|
+
# 0 then an empty array will be returned and no migrations
|
1229
|
+
# will be run.
|
1230
|
+
#
|
1231
|
+
# If the +current_version+ in the schema is greater than
|
1232
|
+
# the +target_version+, then +down+ will be run.
|
1233
|
+
#
|
1234
|
+
# If none of the conditions are met, +up+ will be run with
|
1235
|
+
# the +target_version+.
|
1058
1236
|
def migrate(target_version = nil, &block)
|
1059
1237
|
case
|
1060
1238
|
when target_version.nil?
|
@@ -1068,67 +1246,70 @@ module ActiveRecord
|
|
1068
1246
|
end
|
1069
1247
|
end
|
1070
1248
|
|
1071
|
-
def rollback(steps = 1)
|
1249
|
+
def rollback(steps = 1) # :nodoc:
|
1072
1250
|
move(:down, steps)
|
1073
1251
|
end
|
1074
1252
|
|
1075
|
-
def forward(steps = 1)
|
1253
|
+
def forward(steps = 1) # :nodoc:
|
1076
1254
|
move(:up, steps)
|
1077
1255
|
end
|
1078
1256
|
|
1079
|
-
def up(target_version = nil)
|
1257
|
+
def up(target_version = nil, &block) # :nodoc:
|
1080
1258
|
selected_migrations = if block_given?
|
1081
|
-
migrations.select
|
1259
|
+
migrations.select(&block)
|
1082
1260
|
else
|
1083
1261
|
migrations
|
1084
1262
|
end
|
1085
1263
|
|
1086
|
-
Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate
|
1264
|
+
Migrator.new(:up, selected_migrations, schema_migration, internal_metadata, target_version).migrate
|
1087
1265
|
end
|
1088
1266
|
|
1089
|
-
def down(target_version = nil)
|
1267
|
+
def down(target_version = nil, &block) # :nodoc:
|
1090
1268
|
selected_migrations = if block_given?
|
1091
|
-
migrations.select
|
1269
|
+
migrations.select(&block)
|
1092
1270
|
else
|
1093
1271
|
migrations
|
1094
1272
|
end
|
1095
1273
|
|
1096
|
-
Migrator.new(:down, selected_migrations, schema_migration, target_version).migrate
|
1274
|
+
Migrator.new(:down, selected_migrations, schema_migration, internal_metadata, target_version).migrate
|
1097
1275
|
end
|
1098
1276
|
|
1099
|
-
def run(direction, target_version)
|
1100
|
-
Migrator.new(direction, migrations, schema_migration, target_version).run
|
1277
|
+
def run(direction, target_version) # :nodoc:
|
1278
|
+
Migrator.new(direction, migrations, schema_migration, internal_metadata, target_version).run
|
1101
1279
|
end
|
1102
1280
|
|
1103
|
-
def open
|
1104
|
-
Migrator.new(:up, migrations, schema_migration)
|
1281
|
+
def open # :nodoc:
|
1282
|
+
Migrator.new(:up, migrations, schema_migration, internal_metadata)
|
1105
1283
|
end
|
1106
1284
|
|
1107
|
-
def get_all_versions
|
1285
|
+
def get_all_versions # :nodoc:
|
1108
1286
|
if schema_migration.table_exists?
|
1109
|
-
schema_migration.
|
1287
|
+
schema_migration.integer_versions
|
1110
1288
|
else
|
1111
1289
|
[]
|
1112
1290
|
end
|
1113
1291
|
end
|
1114
1292
|
|
1115
|
-
def current_version
|
1293
|
+
def current_version # :nodoc:
|
1116
1294
|
get_all_versions.max || 0
|
1117
1295
|
rescue ActiveRecord::NoDatabaseError
|
1118
1296
|
end
|
1119
1297
|
|
1120
|
-
def needs_migration?
|
1121
|
-
|
1298
|
+
def needs_migration? # :nodoc:
|
1299
|
+
pending_migration_versions.size > 0
|
1122
1300
|
end
|
1123
1301
|
|
1124
|
-
def
|
1125
|
-
migrations.
|
1302
|
+
def pending_migration_versions # :nodoc:
|
1303
|
+
migrations.collect(&:version) - get_all_versions
|
1126
1304
|
end
|
1127
1305
|
|
1128
|
-
def migrations
|
1306
|
+
def migrations # :nodoc:
|
1129
1307
|
migrations = migration_files.map do |file|
|
1130
1308
|
version, name, scope = parse_migration_filename(file)
|
1131
1309
|
raise IllegalMigrationNameError.new(file) unless version
|
1310
|
+
if validate_timestamp? && !valid_migration_timestamp?(version)
|
1311
|
+
raise InvalidMigrationTimestampError.new(version, name)
|
1312
|
+
end
|
1132
1313
|
version = version.to_i
|
1133
1314
|
name = name.camelize
|
1134
1315
|
|
@@ -1138,43 +1319,55 @@ module ActiveRecord
|
|
1138
1319
|
migrations.sort_by(&:version)
|
1139
1320
|
end
|
1140
1321
|
|
1141
|
-
def migrations_status
|
1322
|
+
def migrations_status # :nodoc:
|
1142
1323
|
db_list = schema_migration.normalized_versions
|
1143
1324
|
|
1144
|
-
file_list = migration_files.
|
1325
|
+
file_list = migration_files.filter_map do |file|
|
1145
1326
|
version, name, scope = parse_migration_filename(file)
|
1146
1327
|
raise IllegalMigrationNameError.new(file) unless version
|
1328
|
+
if validate_timestamp? && !valid_migration_timestamp?(version)
|
1329
|
+
raise InvalidMigrationTimestampError.new(version, name)
|
1330
|
+
end
|
1147
1331
|
version = schema_migration.normalize_migration_number(version)
|
1148
1332
|
status = db_list.delete(version) ? "up" : "down"
|
1149
1333
|
[status, version, (name + scope).humanize]
|
1150
|
-
end
|
1334
|
+
end
|
1151
1335
|
|
1152
1336
|
db_list.map! do |version|
|
1153
1337
|
["up", version, "********** NO FILE **********"]
|
1154
1338
|
end
|
1155
1339
|
|
1156
|
-
(db_list + file_list).sort_by { |_, version, _| version }
|
1340
|
+
(db_list + file_list).sort_by { |_, version, _| version.to_i }
|
1157
1341
|
end
|
1158
1342
|
|
1159
|
-
def current_environment
|
1343
|
+
def current_environment # :nodoc:
|
1160
1344
|
ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
|
1161
1345
|
end
|
1162
1346
|
|
1163
|
-
def protected_environment?
|
1347
|
+
def protected_environment? # :nodoc:
|
1164
1348
|
ActiveRecord::Base.protected_environments.include?(last_stored_environment) if last_stored_environment
|
1165
1349
|
end
|
1166
1350
|
|
1167
|
-
def last_stored_environment
|
1168
|
-
|
1351
|
+
def last_stored_environment # :nodoc:
|
1352
|
+
internal_metadata = connection_pool.internal_metadata
|
1353
|
+
return nil unless internal_metadata.enabled?
|
1169
1354
|
return nil if current_version == 0
|
1170
|
-
raise NoEnvironmentInSchemaError unless
|
1355
|
+
raise NoEnvironmentInSchemaError unless internal_metadata.table_exists?
|
1171
1356
|
|
1172
|
-
environment =
|
1357
|
+
environment = internal_metadata[:environment]
|
1173
1358
|
raise NoEnvironmentInSchemaError unless environment
|
1174
1359
|
environment
|
1175
1360
|
end
|
1176
1361
|
|
1177
1362
|
private
|
1363
|
+
def connection
|
1364
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
1365
|
+
end
|
1366
|
+
|
1367
|
+
def connection_pool
|
1368
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool
|
1369
|
+
end
|
1370
|
+
|
1178
1371
|
def migration_files
|
1179
1372
|
paths = Array(migrations_paths)
|
1180
1373
|
Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
|
@@ -1184,8 +1377,16 @@ module ActiveRecord
|
|
1184
1377
|
File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
|
1185
1378
|
end
|
1186
1379
|
|
1380
|
+
def validate_timestamp?
|
1381
|
+
ActiveRecord.timestamped_migrations && ActiveRecord.validate_migration_timestamps
|
1382
|
+
end
|
1383
|
+
|
1384
|
+
def valid_migration_timestamp?(version)
|
1385
|
+
version.to_i < (Time.now.utc + 1.day).strftime("%Y%m%d%H%M%S").to_i
|
1386
|
+
end
|
1387
|
+
|
1187
1388
|
def move(direction, steps)
|
1188
|
-
migrator = Migrator.new(direction, migrations, schema_migration)
|
1389
|
+
migrator = Migrator.new(direction, migrations, schema_migration, internal_metadata)
|
1189
1390
|
|
1190
1391
|
if current_version != 0 && !migrator.current_migration
|
1191
1392
|
raise UnknownMigrationVersionError.new(current_version)
|
@@ -1210,23 +1411,28 @@ module ActiveRecord
|
|
1210
1411
|
|
1211
1412
|
# For cases where a table doesn't exist like loading from schema cache
|
1212
1413
|
def current_version
|
1213
|
-
|
1414
|
+
connection_pool = ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool
|
1415
|
+
schema_migration = SchemaMigration.new(connection_pool)
|
1416
|
+
internal_metadata = InternalMetadata.new(connection_pool)
|
1417
|
+
|
1418
|
+
MigrationContext.new(migrations_paths, schema_migration, internal_metadata).current_version
|
1214
1419
|
end
|
1215
1420
|
end
|
1216
1421
|
|
1217
1422
|
self.migrations_paths = ["db/migrate"]
|
1218
1423
|
|
1219
|
-
def initialize(direction, migrations, schema_migration, target_version = nil)
|
1424
|
+
def initialize(direction, migrations, schema_migration, internal_metadata, target_version = nil)
|
1220
1425
|
@direction = direction
|
1221
1426
|
@target_version = target_version
|
1222
1427
|
@migrated_versions = nil
|
1223
1428
|
@migrations = migrations
|
1224
1429
|
@schema_migration = schema_migration
|
1430
|
+
@internal_metadata = internal_metadata
|
1225
1431
|
|
1226
1432
|
validate(@migrations)
|
1227
1433
|
|
1228
1434
|
@schema_migration.create_table
|
1229
|
-
|
1435
|
+
@internal_metadata.create_table
|
1230
1436
|
end
|
1231
1437
|
|
1232
1438
|
def current_version
|
@@ -1279,18 +1485,21 @@ module ActiveRecord
|
|
1279
1485
|
end
|
1280
1486
|
|
1281
1487
|
def load_migrated
|
1282
|
-
@migrated_versions = Set.new(@schema_migration.
|
1488
|
+
@migrated_versions = Set.new(@schema_migration.integer_versions)
|
1283
1489
|
end
|
1284
1490
|
|
1285
1491
|
private
|
1492
|
+
def connection
|
1493
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
1494
|
+
end
|
1495
|
+
|
1286
1496
|
# Used for running a specific migration.
|
1287
1497
|
def run_without_lock
|
1288
1498
|
migration = migrations.detect { |m| m.version == @target_version }
|
1289
1499
|
raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
|
1290
|
-
result = execute_migration_in_transaction(migration)
|
1291
1500
|
|
1292
1501
|
record_environment
|
1293
|
-
|
1502
|
+
execute_migration_in_transaction(migration)
|
1294
1503
|
end
|
1295
1504
|
|
1296
1505
|
# Used for running multiple migrations up to or down to a certain value.
|
@@ -1299,15 +1508,15 @@ module ActiveRecord
|
|
1299
1508
|
raise UnknownMigrationVersionError.new(@target_version)
|
1300
1509
|
end
|
1301
1510
|
|
1302
|
-
result = runnable.each(&method(:execute_migration_in_transaction))
|
1303
1511
|
record_environment
|
1304
|
-
|
1512
|
+
runnable.each(&method(:execute_migration_in_transaction))
|
1305
1513
|
end
|
1306
1514
|
|
1307
1515
|
# Stores the current environment in the database.
|
1308
1516
|
def record_environment
|
1309
1517
|
return if down?
|
1310
|
-
|
1518
|
+
|
1519
|
+
@internal_metadata[:environment] = connection.pool.db_config.env_name
|
1311
1520
|
end
|
1312
1521
|
|
1313
1522
|
def ran?(migration)
|
@@ -1359,10 +1568,10 @@ module ActiveRecord
|
|
1359
1568
|
def record_version_state_after_migrating(version)
|
1360
1569
|
if down?
|
1361
1570
|
migrated.delete(version)
|
1362
|
-
@schema_migration.
|
1571
|
+
@schema_migration.delete_version(version.to_s)
|
1363
1572
|
else
|
1364
1573
|
migrated << version
|
1365
|
-
@schema_migration.
|
1574
|
+
@schema_migration.create_version(version.to_s)
|
1366
1575
|
end
|
1367
1576
|
end
|
1368
1577
|
|
@@ -1375,52 +1584,40 @@ module ActiveRecord
|
|
1375
1584
|
end
|
1376
1585
|
|
1377
1586
|
# Wrap the migration in a transaction only if supported by the adapter.
|
1378
|
-
def ddl_transaction(migration)
|
1587
|
+
def ddl_transaction(migration, &block)
|
1379
1588
|
if use_transaction?(migration)
|
1380
|
-
|
1589
|
+
connection.transaction(&block)
|
1381
1590
|
else
|
1382
1591
|
yield
|
1383
1592
|
end
|
1384
1593
|
end
|
1385
1594
|
|
1386
1595
|
def use_transaction?(migration)
|
1387
|
-
!migration.disable_ddl_transaction &&
|
1596
|
+
!migration.disable_ddl_transaction && connection.supports_ddl_transactions?
|
1388
1597
|
end
|
1389
1598
|
|
1390
1599
|
def use_advisory_lock?
|
1391
|
-
|
1600
|
+
connection.advisory_locks_enabled?
|
1392
1601
|
end
|
1393
1602
|
|
1394
1603
|
def with_advisory_lock
|
1395
1604
|
lock_id = generate_migrator_advisory_lock_id
|
1396
1605
|
|
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) }
|
1606
|
+
got_lock = connection.get_advisory_lock(lock_id)
|
1607
|
+
raise ConcurrentMigrationError unless got_lock
|
1608
|
+
load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
|
1609
|
+
yield
|
1417
1610
|
ensure
|
1418
|
-
|
1611
|
+
if got_lock && !connection.release_advisory_lock(lock_id)
|
1612
|
+
raise ConcurrentMigrationError.new(
|
1613
|
+
ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
|
1614
|
+
)
|
1615
|
+
end
|
1419
1616
|
end
|
1420
1617
|
|
1421
1618
|
MIGRATOR_SALT = 2053462845
|
1422
1619
|
def generate_migrator_advisory_lock_id
|
1423
|
-
db_name_hash = Zlib.crc32(
|
1620
|
+
db_name_hash = Zlib.crc32(connection.current_database)
|
1424
1621
|
MIGRATOR_SALT * db_name_hash
|
1425
1622
|
end
|
1426
1623
|
end
|