activerecord 6.1.6 → 7.1.2
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 +1627 -983
- 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 +50 -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 +35 -31
- 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.rb +26 -16
- data/lib/active_record/associations/preloader/association.rb +207 -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 +439 -305
- 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 +25 -10
- data/lib/active_record/attribute_methods/serialization.rb +194 -37
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -3
- data/lib/active_record/attribute_methods/write.rb +10 -13
- data/lib/active_record/attribute_methods.rb +121 -40
- data/lib/active_record/attributes.rb +27 -38
- data/lib/active_record/autosave_association.rb +61 -30
- 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 -34
- 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 +96 -590
- 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 +77 -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 +360 -138
- data/lib/active_record/connection_adapters/abstract/transaction.rb +281 -59
- data/lib/active_record/connection_adapters/abstract_adapter.rb +631 -149
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +285 -156
- 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 +38 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +151 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +104 -53
- 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/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 +394 -74
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +509 -247
- 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 +294 -102
- 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 +254 -0
- data/lib/active_record/connection_adapters.rb +9 -6
- data/lib/active_record/connection_handling.rb +107 -136
- data/lib/active_record/core.rb +202 -223
- data/lib/active_record/counter_cache.rb +46 -25
- data/lib/active_record/database_configurations/connection_url_resolver.rb +2 -1
- data/lib/active_record/database_configurations/database_config.rb +21 -12
- data/lib/active_record/database_configurations/hash_config.rb +84 -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 +61 -15
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +3 -1
- data/lib/active_record/disable_joins_association_relation.rb +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 +224 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +151 -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 +96 -0
- data/lib/active_record/encryption.rb +56 -0
- data/lib/active_record/enum.rb +154 -63
- data/lib/active_record/errors.rb +171 -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 +131 -86
- data/lib/active_record/future_result.rb +164 -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 +36 -21
- data/lib/active_record/locking/pessimistic.rb +15 -6
- data/lib/active_record/log_subscriber.rb +52 -19
- 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 +112 -14
- data/lib/active_record/migration/compatibility.rb +221 -48
- 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 +358 -171
- data/lib/active_record/model_schema.rb +120 -101
- data/lib/active_record/nested_attributes.rb +37 -18
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/normalization.rb +167 -0
- data/lib/active_record/persistence.rb +405 -85
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +3 -21
- 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 +219 -43
- data/lib/active_record/railties/controller_runtime.rb +13 -9
- 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 +241 -80
- 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 +219 -90
- data/lib/active_record/relation/delegation.rb +27 -13
- 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 +4 -6
- 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 +654 -127
- 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 +262 -120
- data/lib/active_record/result.rb +37 -11
- data/lib/active_record/runtime_registry.rb +18 -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 +16 -11
- 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 +225 -136
- 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 +123 -99
- data/lib/active_record/timestamp.rb +29 -18
- 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 +0 -12
- 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 +139 -19
- 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 +93 -13
- 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,12 +363,12 @@ 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
|
# bin/rails generate migration MyNewMigration
|
@@ -376,7 +383,7 @@ module ActiveRecord
|
|
376
383
|
# bin/rails generate migration add_fieldname_to_tablename fieldname:string
|
377
384
|
#
|
378
385
|
# This will generate the file <tt>timestamp_add_fieldname_to_tablename.rb</tt>, which will look like this:
|
379
|
-
# class AddFieldnameToTablename < ActiveRecord::Migration[
|
386
|
+
# class AddFieldnameToTablename < ActiveRecord::Migration[7.1]
|
380
387
|
# def change
|
381
388
|
# add_column :tablenames, :fieldname, :string
|
382
389
|
# end
|
@@ -395,14 +402,14 @@ module ActiveRecord
|
|
395
402
|
# wish to rollback last few migrations. <tt>bin/rails db:rollback STEP=2</tt> will rollback
|
396
403
|
# the latest two migrations.
|
397
404
|
#
|
398
|
-
# If any of the migrations throw an
|
405
|
+
# If any of the migrations throw an ActiveRecord::IrreversibleMigration exception,
|
399
406
|
# that step will fail and you'll have some manual work to do.
|
400
407
|
#
|
401
408
|
# == More examples
|
402
409
|
#
|
403
410
|
# Not all migrations change the schema. Some just fix the data:
|
404
411
|
#
|
405
|
-
# class RemoveEmptyTags < ActiveRecord::Migration[
|
412
|
+
# class RemoveEmptyTags < ActiveRecord::Migration[7.1]
|
406
413
|
# def up
|
407
414
|
# Tag.all.each { |tag| tag.destroy if tag.pages.empty? }
|
408
415
|
# end
|
@@ -415,7 +422,7 @@ module ActiveRecord
|
|
415
422
|
#
|
416
423
|
# Others remove columns when they migrate up instead of down:
|
417
424
|
#
|
418
|
-
# class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[
|
425
|
+
# class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[7.1]
|
419
426
|
# def up
|
420
427
|
# remove_column :items, :incomplete_items_count
|
421
428
|
# remove_column :items, :completed_items_count
|
@@ -429,7 +436,7 @@ module ActiveRecord
|
|
429
436
|
#
|
430
437
|
# And sometimes you need to do something in SQL not abstracted directly by migrations:
|
431
438
|
#
|
432
|
-
# class MakeJoinUnique < ActiveRecord::Migration[
|
439
|
+
# class MakeJoinUnique < ActiveRecord::Migration[7.1]
|
433
440
|
# def up
|
434
441
|
# execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)"
|
435
442
|
# end
|
@@ -446,7 +453,7 @@ module ActiveRecord
|
|
446
453
|
# <tt>Base#reset_column_information</tt> in order to ensure that the model has the
|
447
454
|
# latest column data from after the new column was added. Example:
|
448
455
|
#
|
449
|
-
# class AddPeopleSalary < ActiveRecord::Migration[
|
456
|
+
# class AddPeopleSalary < ActiveRecord::Migration[7.1]
|
450
457
|
# def up
|
451
458
|
# add_column :people, :salary, :integer
|
452
459
|
# Person.reset_column_information
|
@@ -482,7 +489,7 @@ module ActiveRecord
|
|
482
489
|
#
|
483
490
|
# == Timestamped Migrations
|
484
491
|
#
|
485
|
-
# By default, Rails generates migrations that look like:
|
492
|
+
# By default, \Rails generates migrations that look like:
|
486
493
|
#
|
487
494
|
# 20080717013526_your_migration_name.rb
|
488
495
|
#
|
@@ -504,7 +511,7 @@ module ActiveRecord
|
|
504
511
|
# To define a reversible migration, define the +change+ method in your
|
505
512
|
# migration like this:
|
506
513
|
#
|
507
|
-
# class TenderloveMigration < ActiveRecord::Migration[
|
514
|
+
# class TenderloveMigration < ActiveRecord::Migration[7.1]
|
508
515
|
# def change
|
509
516
|
# create_table(:horses) do |t|
|
510
517
|
# t.column :content, :text
|
@@ -521,11 +528,11 @@ module ActiveRecord
|
|
521
528
|
# as before.
|
522
529
|
#
|
523
530
|
# If a command cannot be reversed, an
|
524
|
-
#
|
531
|
+
# ActiveRecord::IrreversibleMigration exception will be raised when
|
525
532
|
# the migration is moving down.
|
526
533
|
#
|
527
534
|
# For a list of commands that are reversible, please see
|
528
|
-
#
|
535
|
+
# +ActiveRecord::Migration::CommandRecorder+.
|
529
536
|
#
|
530
537
|
# == Transactional Migrations
|
531
538
|
#
|
@@ -534,7 +541,7 @@ module ActiveRecord
|
|
534
541
|
# can't execute inside a transaction though, and for these situations
|
535
542
|
# you can turn the automatic transactions off.
|
536
543
|
#
|
537
|
-
# class ChangeEnum < ActiveRecord::Migration[
|
544
|
+
# class ChangeEnum < ActiveRecord::Migration[7.1]
|
538
545
|
# disable_ddl_transaction!
|
539
546
|
#
|
540
547
|
# def up
|
@@ -548,18 +555,57 @@ module ActiveRecord
|
|
548
555
|
autoload :CommandRecorder, "active_record/migration/command_recorder"
|
549
556
|
autoload :Compatibility, "active_record/migration/compatibility"
|
550
557
|
autoload :JoinTable, "active_record/migration/join_table"
|
558
|
+
autoload :ExecutionStrategy, "active_record/migration/execution_strategy"
|
559
|
+
autoload :DefaultStrategy, "active_record/migration/default_strategy"
|
551
560
|
|
552
561
|
# This must be defined before the inherited hook, below
|
553
|
-
class Current < Migration
|
562
|
+
class Current < Migration # :nodoc:
|
563
|
+
def create_table(table_name, **options)
|
564
|
+
if block_given?
|
565
|
+
super { |t| yield compatible_table_definition(t) }
|
566
|
+
else
|
567
|
+
super
|
568
|
+
end
|
569
|
+
end
|
570
|
+
|
571
|
+
def change_table(table_name, **options)
|
572
|
+
if block_given?
|
573
|
+
super { |t| yield compatible_table_definition(t) }
|
574
|
+
else
|
575
|
+
super
|
576
|
+
end
|
577
|
+
end
|
578
|
+
|
579
|
+
def create_join_table(table_1, table_2, **options)
|
580
|
+
if block_given?
|
581
|
+
super { |t| yield compatible_table_definition(t) }
|
582
|
+
else
|
583
|
+
super
|
584
|
+
end
|
585
|
+
end
|
586
|
+
|
587
|
+
def drop_table(table_name, **options)
|
588
|
+
if block_given?
|
589
|
+
super { |t| yield compatible_table_definition(t) }
|
590
|
+
else
|
591
|
+
super
|
592
|
+
end
|
593
|
+
end
|
594
|
+
|
595
|
+
def compatible_table_definition(t)
|
596
|
+
t
|
597
|
+
end
|
554
598
|
end
|
555
599
|
|
556
|
-
def self.inherited(subclass)
|
600
|
+
def self.inherited(subclass) # :nodoc:
|
557
601
|
super
|
558
602
|
if subclass.superclass == Migration
|
603
|
+
major = ActiveRecord::VERSION::MAJOR
|
604
|
+
minor = ActiveRecord::VERSION::MINOR
|
559
605
|
raise StandardError, "Directly inheriting from ActiveRecord::Migration is not supported. " \
|
560
|
-
"Please specify the
|
606
|
+
"Please specify the Active Record release the migration was written for:\n" \
|
561
607
|
"\n" \
|
562
|
-
" class #{subclass} < ActiveRecord::Migration[
|
608
|
+
" class #{subclass} < ActiveRecord::Migration[#{major}.#{minor}]"
|
563
609
|
end
|
564
610
|
end
|
565
611
|
|
@@ -571,10 +617,17 @@ module ActiveRecord
|
|
571
617
|
ActiveRecord::VERSION::STRING.to_f
|
572
618
|
end
|
573
619
|
|
574
|
-
MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/
|
620
|
+
MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/ # :nodoc:
|
621
|
+
|
622
|
+
def self.valid_version_format?(version_string) # :nodoc:
|
623
|
+
[
|
624
|
+
MigrationFilenameRegexp,
|
625
|
+
/\A\d(_?\d)*\z/ # integer with optional underscores
|
626
|
+
].any? { |pattern| pattern.match?(version_string) }
|
627
|
+
end
|
575
628
|
|
576
629
|
# 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
|
630
|
+
# loading a web page if <tt>config.active_record.migration_error</tt> is set to +:page_load+.
|
578
631
|
class CheckPending
|
579
632
|
def initialize(app, file_watcher: ActiveSupport::FileUpdateChecker)
|
580
633
|
@app = app
|
@@ -587,7 +640,7 @@ module ActiveRecord
|
|
587
640
|
@mutex.synchronize do
|
588
641
|
@watcher ||= build_watcher do
|
589
642
|
@needs_check = true
|
590
|
-
ActiveRecord::Migration.
|
643
|
+
ActiveRecord::Migration.check_pending_migrations
|
591
644
|
@needs_check = false
|
592
645
|
end
|
593
646
|
|
@@ -603,61 +656,84 @@ module ActiveRecord
|
|
603
656
|
|
604
657
|
private
|
605
658
|
def build_watcher(&block)
|
606
|
-
|
659
|
+
current_environment = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
|
660
|
+
all_configs = ActiveRecord::Base.configurations.configs_for(env_name: current_environment)
|
661
|
+
paths = all_configs.flat_map { |config| config.migrations_paths || Migrator.migrations_paths }.uniq
|
607
662
|
@file_watcher.new([], paths.index_with(["rb"]), &block)
|
608
663
|
end
|
609
664
|
|
610
665
|
def connection
|
611
|
-
ActiveRecord::
|
666
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
612
667
|
end
|
613
668
|
end
|
614
669
|
|
615
670
|
class << self
|
616
|
-
attr_accessor :delegate
|
617
|
-
attr_accessor :disable_ddl_transaction
|
671
|
+
attr_accessor :delegate # :nodoc:
|
672
|
+
attr_accessor :disable_ddl_transaction # :nodoc:
|
618
673
|
|
619
|
-
def nearest_delegate
|
674
|
+
def nearest_delegate # :nodoc:
|
620
675
|
delegate || superclass.nearest_delegate
|
621
676
|
end
|
622
677
|
|
623
|
-
# Raises
|
624
|
-
|
625
|
-
|
678
|
+
# Raises ActiveRecord::PendingMigrationError error if any migrations are pending.
|
679
|
+
#
|
680
|
+
# This is deprecated in favor of +check_all_pending!+
|
681
|
+
def check_pending!(connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection)
|
682
|
+
ActiveRecord.deprecator.warn(<<-MSG.squish)
|
683
|
+
The `check_pending!` method is deprecated in favor of `check_all_pending!`. The
|
684
|
+
new implementation will loop through all available database configurations and find
|
685
|
+
pending migrations. The prior implementation did not permit this.
|
686
|
+
MSG
|
687
|
+
|
688
|
+
pending_migrations = connection.migration_context.open.pending_migrations
|
689
|
+
|
690
|
+
if pending_migrations.any?
|
691
|
+
raise ActiveRecord::PendingMigrationError.new(pending_migrations: pending_migrations)
|
692
|
+
end
|
626
693
|
end
|
627
694
|
|
628
|
-
|
629
|
-
|
630
|
-
|
695
|
+
# Raises ActiveRecord::PendingMigrationError error if any migrations are pending
|
696
|
+
# for all database configurations in an environment.
|
697
|
+
def check_all_pending!
|
698
|
+
pending_migrations = []
|
699
|
+
|
700
|
+
ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: env) do |connection|
|
701
|
+
if pending = connection.migration_context.open.pending_migrations
|
702
|
+
pending_migrations << pending
|
703
|
+
end
|
704
|
+
end
|
705
|
+
|
706
|
+
migrations = pending_migrations.flatten
|
631
707
|
|
632
|
-
|
633
|
-
|
708
|
+
if migrations.any?
|
709
|
+
raise ActiveRecord::PendingMigrationError.new(pending_migrations: migrations)
|
634
710
|
end
|
711
|
+
end
|
635
712
|
|
636
|
-
|
713
|
+
def load_schema_if_pending!
|
714
|
+
if any_schema_needs_update?
|
637
715
|
# Roundtrip to Rake to allow plugins to hook into database initialization.
|
638
716
|
root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
|
717
|
+
|
639
718
|
FileUtils.cd(root) do
|
640
|
-
Base.clear_all_connections!
|
719
|
+
Base.connection_handler.clear_all_connections!(:all)
|
641
720
|
system("bin/rails db:test:prepare")
|
642
721
|
end
|
643
722
|
end
|
644
723
|
|
645
|
-
|
646
|
-
Base.establish_connection(current_db_config)
|
647
|
-
|
648
|
-
check_pending!
|
724
|
+
check_pending_migrations
|
649
725
|
end
|
650
726
|
|
651
|
-
def maintain_test_schema!
|
652
|
-
if ActiveRecord
|
727
|
+
def maintain_test_schema! # :nodoc:
|
728
|
+
if ActiveRecord.maintain_test_schema
|
653
729
|
suppress_messages { load_schema_if_pending! }
|
654
730
|
end
|
655
731
|
end
|
656
732
|
|
657
|
-
def method_missing(name, *args, &block)
|
733
|
+
def method_missing(name, *args, &block) # :nodoc:
|
658
734
|
nearest_delegate.send(name, *args, &block)
|
659
735
|
end
|
660
|
-
ruby2_keywords(:method_missing)
|
736
|
+
ruby2_keywords(:method_missing)
|
661
737
|
|
662
738
|
def migrate(direction)
|
663
739
|
new.migrate direction
|
@@ -670,9 +746,46 @@ module ActiveRecord
|
|
670
746
|
def disable_ddl_transaction!
|
671
747
|
@disable_ddl_transaction = true
|
672
748
|
end
|
749
|
+
|
750
|
+
def check_pending_migrations # :nodoc:
|
751
|
+
migrations = pending_migrations
|
752
|
+
|
753
|
+
if migrations.any?
|
754
|
+
raise ActiveRecord::PendingMigrationError.new(pending_migrations: migrations)
|
755
|
+
end
|
756
|
+
end
|
757
|
+
|
758
|
+
private
|
759
|
+
def any_schema_needs_update?
|
760
|
+
!db_configs_in_current_env.all? do |db_config|
|
761
|
+
Tasks::DatabaseTasks.schema_up_to_date?(db_config, ActiveRecord.schema_format)
|
762
|
+
end
|
763
|
+
end
|
764
|
+
|
765
|
+
def db_configs_in_current_env
|
766
|
+
ActiveRecord::Base.configurations.configs_for(env_name: env)
|
767
|
+
end
|
768
|
+
|
769
|
+
def pending_migrations
|
770
|
+
pending_migrations = []
|
771
|
+
|
772
|
+
ActiveRecord::Base.configurations.configs_for(env_name: env).each do |db_config|
|
773
|
+
ActiveRecord::PendingMigrationConnection.establish_temporary_connection(db_config) do |conn|
|
774
|
+
if pending = conn.migration_context.open.pending_migrations
|
775
|
+
pending_migrations << pending
|
776
|
+
end
|
777
|
+
end
|
778
|
+
end
|
779
|
+
|
780
|
+
pending_migrations.flatten
|
781
|
+
end
|
782
|
+
|
783
|
+
def env
|
784
|
+
ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
|
785
|
+
end
|
673
786
|
end
|
674
787
|
|
675
|
-
def disable_ddl_transaction
|
788
|
+
def disable_ddl_transaction # :nodoc:
|
676
789
|
self.class.disable_ddl_transaction
|
677
790
|
end
|
678
791
|
|
@@ -685,6 +798,10 @@ module ActiveRecord
|
|
685
798
|
@connection = nil
|
686
799
|
end
|
687
800
|
|
801
|
+
def execution_strategy
|
802
|
+
@execution_strategy ||= ActiveRecord.migration_strategy.new(self)
|
803
|
+
end
|
804
|
+
|
688
805
|
self.verbose = true
|
689
806
|
# instantiate the delegate object after initialize is defined
|
690
807
|
self.delegate = new
|
@@ -696,7 +813,7 @@ module ActiveRecord
|
|
696
813
|
# and create the table 'apples' on the way up, and the reverse
|
697
814
|
# on the way down.
|
698
815
|
#
|
699
|
-
# class FixTLMigration < ActiveRecord::Migration[
|
816
|
+
# class FixTLMigration < ActiveRecord::Migration[7.1]
|
700
817
|
# def change
|
701
818
|
# revert do
|
702
819
|
# create_table(:horses) do |t|
|
@@ -715,7 +832,7 @@ module ActiveRecord
|
|
715
832
|
#
|
716
833
|
# require_relative "20121212123456_tenderlove_migration"
|
717
834
|
#
|
718
|
-
# class FixupTLMigration < ActiveRecord::Migration[
|
835
|
+
# class FixupTLMigration < ActiveRecord::Migration[7.1]
|
719
836
|
# def change
|
720
837
|
# revert TenderloveMigration
|
721
838
|
#
|
@@ -726,16 +843,16 @@ module ActiveRecord
|
|
726
843
|
# end
|
727
844
|
#
|
728
845
|
# This command can be nested.
|
729
|
-
def revert(*migration_classes)
|
846
|
+
def revert(*migration_classes, &block)
|
730
847
|
run(*migration_classes.reverse, revert: true) unless migration_classes.empty?
|
731
848
|
if block_given?
|
732
849
|
if connection.respond_to? :revert
|
733
|
-
connection.revert
|
850
|
+
connection.revert(&block)
|
734
851
|
else
|
735
852
|
recorder = command_recorder
|
736
853
|
@connection = recorder
|
737
854
|
suppress_messages do
|
738
|
-
connection.revert
|
855
|
+
connection.revert(&block)
|
739
856
|
end
|
740
857
|
@connection = recorder.delegate
|
741
858
|
recorder.replay(self)
|
@@ -747,7 +864,7 @@ module ActiveRecord
|
|
747
864
|
connection.respond_to?(:reverting) && connection.reverting
|
748
865
|
end
|
749
866
|
|
750
|
-
ReversibleBlockHelper = Struct.new(:reverting) do
|
867
|
+
ReversibleBlockHelper = Struct.new(:reverting) do # :nodoc:
|
751
868
|
def up
|
752
869
|
yield unless reverting
|
753
870
|
end
|
@@ -766,7 +883,7 @@ module ActiveRecord
|
|
766
883
|
# when the three columns 'first_name', 'last_name' and 'full_name' exist,
|
767
884
|
# even when migrating down:
|
768
885
|
#
|
769
|
-
# class SplitNameMigration < ActiveRecord::Migration[
|
886
|
+
# class SplitNameMigration < ActiveRecord::Migration[7.1]
|
770
887
|
# def change
|
771
888
|
# add_column :users, :first_name, :string
|
772
889
|
# add_column :users, :last_name, :string
|
@@ -794,7 +911,7 @@ module ActiveRecord
|
|
794
911
|
# In the following example, the new column +published+ will be given
|
795
912
|
# the value +true+ for all existing records.
|
796
913
|
#
|
797
|
-
# class AddPublishedToPosts < ActiveRecord::Migration[
|
914
|
+
# class AddPublishedToPosts < ActiveRecord::Migration[7.1]
|
798
915
|
# def change
|
799
916
|
# add_column :posts, :published, :boolean, default: false
|
800
917
|
# up_only do
|
@@ -802,14 +919,15 @@ module ActiveRecord
|
|
802
919
|
# end
|
803
920
|
# end
|
804
921
|
# end
|
805
|
-
def up_only
|
806
|
-
execute_block
|
922
|
+
def up_only(&block)
|
923
|
+
execute_block(&block) unless reverting?
|
807
924
|
end
|
808
925
|
|
809
926
|
# Runs the given migration classes.
|
810
927
|
# Last argument can specify options:
|
811
|
-
#
|
812
|
-
# -
|
928
|
+
#
|
929
|
+
# - +:direction+ - Default is +:up+.
|
930
|
+
# - +:revert+ - Default is +false+.
|
813
931
|
def run(*migration_classes)
|
814
932
|
opts = migration_classes.extract_options!
|
815
933
|
dir = opts[:direction] || :up
|
@@ -846,7 +964,7 @@ module ActiveRecord
|
|
846
964
|
end
|
847
965
|
|
848
966
|
time = nil
|
849
|
-
ActiveRecord::
|
967
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection.pool.with_connection do |conn|
|
850
968
|
time = Benchmark.measure do
|
851
969
|
exec_migration(conn, direction)
|
852
970
|
end
|
@@ -871,6 +989,7 @@ module ActiveRecord
|
|
871
989
|
end
|
872
990
|
ensure
|
873
991
|
@connection = nil
|
992
|
+
@execution_strategy = nil
|
874
993
|
end
|
875
994
|
|
876
995
|
def write(text = "")
|
@@ -909,38 +1028,37 @@ module ActiveRecord
|
|
909
1028
|
end
|
910
1029
|
|
911
1030
|
def connection
|
912
|
-
@connection || ActiveRecord::
|
1031
|
+
@connection || ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
913
1032
|
end
|
914
1033
|
|
915
1034
|
def method_missing(method, *arguments, &block)
|
916
|
-
|
917
|
-
|
918
|
-
say_with_time "#{method}(#{arg_list})" do
|
1035
|
+
say_with_time "#{method}(#{format_arguments(arguments)})" do
|
919
1036
|
unless connection.respond_to? :revert
|
920
1037
|
unless arguments.empty? || [:execute, :enable_extension, :disable_extension].include?(method)
|
921
1038
|
arguments[0] = proper_table_name(arguments.first, table_name_options)
|
922
|
-
if
|
1039
|
+
if method == :rename_table ||
|
923
1040
|
(method == :remove_foreign_key && !arguments.second.is_a?(Hash))
|
924
1041
|
arguments[1] = proper_table_name(arguments.second, table_name_options)
|
925
1042
|
end
|
926
1043
|
end
|
927
1044
|
end
|
928
|
-
return super unless
|
929
|
-
|
1045
|
+
return super unless execution_strategy.respond_to?(method)
|
1046
|
+
execution_strategy.send(method, *arguments, &block)
|
930
1047
|
end
|
931
1048
|
end
|
932
|
-
ruby2_keywords(:method_missing)
|
1049
|
+
ruby2_keywords(:method_missing)
|
933
1050
|
|
934
1051
|
def copy(destination, sources, options = {})
|
935
1052
|
copied = []
|
936
|
-
schema_migration = options[:schema_migration] || ActiveRecord::SchemaMigration
|
937
1053
|
|
938
1054
|
FileUtils.mkdir_p(destination) unless File.exist?(destination)
|
1055
|
+
schema_migration = SchemaMigration::NullSchemaMigration.new
|
1056
|
+
internal_metadata = InternalMetadata::NullInternalMetadata.new
|
939
1057
|
|
940
|
-
destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration).migrations
|
1058
|
+
destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration, internal_metadata).migrations
|
941
1059
|
last = destination_migrations.last
|
942
1060
|
sources.each do |scope, path|
|
943
|
-
source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration).migrations
|
1061
|
+
source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration, internal_metadata).migrations
|
944
1062
|
|
945
1063
|
source_migrations.each do |migration|
|
946
1064
|
source = File.binread(migration.filename)
|
@@ -955,6 +1073,12 @@ module ActiveRecord
|
|
955
1073
|
magic_comments << magic_comment; ""
|
956
1074
|
end || break
|
957
1075
|
end
|
1076
|
+
|
1077
|
+
if !magic_comments.empty? && source.start_with?("\n")
|
1078
|
+
magic_comments << "\n"
|
1079
|
+
source = source[1..-1]
|
1080
|
+
end
|
1081
|
+
|
958
1082
|
source = "#{magic_comments}#{inserted_comment}#{source}"
|
959
1083
|
|
960
1084
|
if duplicate = destination_migrations.detect { |m| m.name == migration.name }
|
@@ -992,16 +1116,16 @@ module ActiveRecord
|
|
992
1116
|
|
993
1117
|
# Determines the version number of the next migration.
|
994
1118
|
def next_migration_number(number)
|
995
|
-
if ActiveRecord
|
1119
|
+
if ActiveRecord.timestamped_migrations
|
996
1120
|
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max
|
997
1121
|
else
|
998
|
-
|
1122
|
+
"%.3d" % number.to_i
|
999
1123
|
end
|
1000
1124
|
end
|
1001
1125
|
|
1002
1126
|
# Builds a hash for use in ActiveRecord::Migration#proper_table_name using
|
1003
1127
|
# the Active Record object's table_name prefix and suffix
|
1004
|
-
def table_name_options(config = ActiveRecord::Base)
|
1128
|
+
def table_name_options(config = ActiveRecord::Base) # :nodoc:
|
1005
1129
|
{
|
1006
1130
|
table_name_prefix: config.table_name_prefix,
|
1007
1131
|
table_name_suffix: config.table_name_suffix
|
@@ -1017,6 +1141,22 @@ module ActiveRecord
|
|
1017
1141
|
end
|
1018
1142
|
end
|
1019
1143
|
|
1144
|
+
def format_arguments(arguments)
|
1145
|
+
arg_list = arguments[0...-1].map(&:inspect)
|
1146
|
+
last_arg = arguments.last
|
1147
|
+
if last_arg.is_a?(Hash)
|
1148
|
+
last_arg = last_arg.reject { |k, _v| internal_option?(k) }
|
1149
|
+
arg_list << last_arg.inspect unless last_arg.empty?
|
1150
|
+
else
|
1151
|
+
arg_list << last_arg.inspect
|
1152
|
+
end
|
1153
|
+
arg_list.join(", ")
|
1154
|
+
end
|
1155
|
+
|
1156
|
+
def internal_option?(option_name)
|
1157
|
+
option_name.start_with?("_")
|
1158
|
+
end
|
1159
|
+
|
1020
1160
|
def command_recorder
|
1021
1161
|
CommandRecorder.new(connection)
|
1022
1162
|
end
|
@@ -1042,19 +1182,66 @@ module ActiveRecord
|
|
1042
1182
|
end
|
1043
1183
|
|
1044
1184
|
def load_migration
|
1045
|
-
|
1185
|
+
Object.send(:remove_const, name) rescue nil
|
1186
|
+
|
1187
|
+
load(File.expand_path(filename))
|
1046
1188
|
name.constantize.new(name, version)
|
1047
1189
|
end
|
1048
1190
|
end
|
1049
1191
|
|
1050
|
-
|
1051
|
-
|
1192
|
+
# = \Migration \Context
|
1193
|
+
#
|
1194
|
+
# MigrationContext sets the context in which a migration is run.
|
1195
|
+
#
|
1196
|
+
# A migration context requires the path to the migrations is set
|
1197
|
+
# in the +migrations_paths+ parameter. Optionally a +schema_migration+
|
1198
|
+
# class can be provided. Multiple database applications will instantiate
|
1199
|
+
# a +SchemaMigration+ object per database. From the Rake tasks, \Rails will
|
1200
|
+
# handle this for you.
|
1201
|
+
class MigrationContext
|
1202
|
+
attr_reader :migrations_paths, :schema_migration, :internal_metadata
|
1203
|
+
|
1204
|
+
def initialize(migrations_paths, schema_migration = nil, internal_metadata = nil)
|
1205
|
+
if schema_migration == SchemaMigration
|
1206
|
+
ActiveRecord.deprecator.warn(<<-MSG.squish)
|
1207
|
+
SchemaMigration no longer inherits from ActiveRecord::Base. If you want
|
1208
|
+
to use the default connection, remove this argument. If you want to use a
|
1209
|
+
specific connection, instantiate MigrationContext with the connection's schema
|
1210
|
+
migration, for example `MigrationContext.new(path, Dog.connection.schema_migration)`.
|
1211
|
+
MSG
|
1212
|
+
|
1213
|
+
schema_migration = nil
|
1214
|
+
end
|
1215
|
+
|
1216
|
+
if internal_metadata == InternalMetadata
|
1217
|
+
ActiveRecord.deprecator.warn(<<-MSG.squish)
|
1218
|
+
SchemaMigration no longer inherits from ActiveRecord::Base. If you want
|
1219
|
+
to use the default connection, remove this argument. If you want to use a
|
1220
|
+
specific connection, instantiate MigrationContext with the connection's internal
|
1221
|
+
metadata, for example `MigrationContext.new(path, nil, Dog.connection.internal_metadata)`.
|
1222
|
+
MSG
|
1223
|
+
|
1224
|
+
internal_metadata = nil
|
1225
|
+
end
|
1052
1226
|
|
1053
|
-
def initialize(migrations_paths, schema_migration)
|
1054
1227
|
@migrations_paths = migrations_paths
|
1055
|
-
@schema_migration = schema_migration
|
1228
|
+
@schema_migration = schema_migration || SchemaMigration.new(connection)
|
1229
|
+
@internal_metadata = internal_metadata || InternalMetadata.new(connection)
|
1056
1230
|
end
|
1057
1231
|
|
1232
|
+
# Runs the migrations in the +migrations_path+.
|
1233
|
+
#
|
1234
|
+
# If +target_version+ is +nil+, +migrate+ will run +up+.
|
1235
|
+
#
|
1236
|
+
# If the +current_version+ and +target_version+ are both
|
1237
|
+
# 0 then an empty array will be returned and no migrations
|
1238
|
+
# will be run.
|
1239
|
+
#
|
1240
|
+
# If the +current_version+ in the schema is greater than
|
1241
|
+
# the +target_version+, then +down+ will be run.
|
1242
|
+
#
|
1243
|
+
# If none of the conditions are met, +up+ will be run with
|
1244
|
+
# the +target_version+.
|
1058
1245
|
def migrate(target_version = nil, &block)
|
1059
1246
|
case
|
1060
1247
|
when target_version.nil?
|
@@ -1068,64 +1255,64 @@ module ActiveRecord
|
|
1068
1255
|
end
|
1069
1256
|
end
|
1070
1257
|
|
1071
|
-
def rollback(steps = 1)
|
1258
|
+
def rollback(steps = 1) # :nodoc:
|
1072
1259
|
move(:down, steps)
|
1073
1260
|
end
|
1074
1261
|
|
1075
|
-
def forward(steps = 1)
|
1262
|
+
def forward(steps = 1) # :nodoc:
|
1076
1263
|
move(:up, steps)
|
1077
1264
|
end
|
1078
1265
|
|
1079
|
-
def up(target_version = nil)
|
1266
|
+
def up(target_version = nil, &block) # :nodoc:
|
1080
1267
|
selected_migrations = if block_given?
|
1081
|
-
migrations.select
|
1268
|
+
migrations.select(&block)
|
1082
1269
|
else
|
1083
1270
|
migrations
|
1084
1271
|
end
|
1085
1272
|
|
1086
|
-
Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate
|
1273
|
+
Migrator.new(:up, selected_migrations, schema_migration, internal_metadata, target_version).migrate
|
1087
1274
|
end
|
1088
1275
|
|
1089
|
-
def down(target_version = nil)
|
1276
|
+
def down(target_version = nil, &block) # :nodoc:
|
1090
1277
|
selected_migrations = if block_given?
|
1091
|
-
migrations.select
|
1278
|
+
migrations.select(&block)
|
1092
1279
|
else
|
1093
1280
|
migrations
|
1094
1281
|
end
|
1095
1282
|
|
1096
|
-
Migrator.new(:down, selected_migrations, schema_migration, target_version).migrate
|
1283
|
+
Migrator.new(:down, selected_migrations, schema_migration, internal_metadata, target_version).migrate
|
1097
1284
|
end
|
1098
1285
|
|
1099
|
-
def run(direction, target_version)
|
1100
|
-
Migrator.new(direction, migrations, schema_migration, target_version).run
|
1286
|
+
def run(direction, target_version) # :nodoc:
|
1287
|
+
Migrator.new(direction, migrations, schema_migration, internal_metadata, target_version).run
|
1101
1288
|
end
|
1102
1289
|
|
1103
|
-
def open
|
1104
|
-
Migrator.new(:up, migrations, schema_migration)
|
1290
|
+
def open # :nodoc:
|
1291
|
+
Migrator.new(:up, migrations, schema_migration, internal_metadata)
|
1105
1292
|
end
|
1106
1293
|
|
1107
|
-
def get_all_versions
|
1294
|
+
def get_all_versions # :nodoc:
|
1108
1295
|
if schema_migration.table_exists?
|
1109
|
-
schema_migration.
|
1296
|
+
schema_migration.integer_versions
|
1110
1297
|
else
|
1111
1298
|
[]
|
1112
1299
|
end
|
1113
1300
|
end
|
1114
1301
|
|
1115
|
-
def current_version
|
1302
|
+
def current_version # :nodoc:
|
1116
1303
|
get_all_versions.max || 0
|
1117
1304
|
rescue ActiveRecord::NoDatabaseError
|
1118
1305
|
end
|
1119
1306
|
|
1120
|
-
def needs_migration?
|
1121
|
-
|
1307
|
+
def needs_migration? # :nodoc:
|
1308
|
+
pending_migration_versions.size > 0
|
1122
1309
|
end
|
1123
1310
|
|
1124
|
-
def
|
1125
|
-
migrations.
|
1311
|
+
def pending_migration_versions # :nodoc:
|
1312
|
+
migrations.collect(&:version) - get_all_versions
|
1126
1313
|
end
|
1127
1314
|
|
1128
|
-
def migrations
|
1315
|
+
def migrations # :nodoc:
|
1129
1316
|
migrations = migration_files.map do |file|
|
1130
1317
|
version, name, scope = parse_migration_filename(file)
|
1131
1318
|
raise IllegalMigrationNameError.new(file) unless version
|
@@ -1138,43 +1325,47 @@ module ActiveRecord
|
|
1138
1325
|
migrations.sort_by(&:version)
|
1139
1326
|
end
|
1140
1327
|
|
1141
|
-
def migrations_status
|
1328
|
+
def migrations_status # :nodoc:
|
1142
1329
|
db_list = schema_migration.normalized_versions
|
1143
1330
|
|
1144
|
-
file_list = migration_files.
|
1331
|
+
file_list = migration_files.filter_map do |file|
|
1145
1332
|
version, name, scope = parse_migration_filename(file)
|
1146
1333
|
raise IllegalMigrationNameError.new(file) unless version
|
1147
1334
|
version = schema_migration.normalize_migration_number(version)
|
1148
1335
|
status = db_list.delete(version) ? "up" : "down"
|
1149
1336
|
[status, version, (name + scope).humanize]
|
1150
|
-
end
|
1337
|
+
end
|
1151
1338
|
|
1152
1339
|
db_list.map! do |version|
|
1153
1340
|
["up", version, "********** NO FILE **********"]
|
1154
1341
|
end
|
1155
1342
|
|
1156
|
-
(db_list + file_list).sort_by { |_, version, _| version }
|
1343
|
+
(db_list + file_list).sort_by { |_, version, _| version.to_i }
|
1157
1344
|
end
|
1158
1345
|
|
1159
|
-
def current_environment
|
1346
|
+
def current_environment # :nodoc:
|
1160
1347
|
ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
|
1161
1348
|
end
|
1162
1349
|
|
1163
|
-
def protected_environment?
|
1350
|
+
def protected_environment? # :nodoc:
|
1164
1351
|
ActiveRecord::Base.protected_environments.include?(last_stored_environment) if last_stored_environment
|
1165
1352
|
end
|
1166
1353
|
|
1167
|
-
def last_stored_environment
|
1168
|
-
return nil unless
|
1354
|
+
def last_stored_environment # :nodoc:
|
1355
|
+
return nil unless connection.internal_metadata.enabled?
|
1169
1356
|
return nil if current_version == 0
|
1170
|
-
raise NoEnvironmentInSchemaError unless
|
1357
|
+
raise NoEnvironmentInSchemaError unless connection.internal_metadata.table_exists?
|
1171
1358
|
|
1172
|
-
environment =
|
1359
|
+
environment = connection.internal_metadata[:environment]
|
1173
1360
|
raise NoEnvironmentInSchemaError unless environment
|
1174
1361
|
environment
|
1175
1362
|
end
|
1176
1363
|
|
1177
1364
|
private
|
1365
|
+
def connection
|
1366
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
1367
|
+
end
|
1368
|
+
|
1178
1369
|
def migration_files
|
1179
1370
|
paths = Array(migrations_paths)
|
1180
1371
|
Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
|
@@ -1185,7 +1376,7 @@ module ActiveRecord
|
|
1185
1376
|
end
|
1186
1377
|
|
1187
1378
|
def move(direction, steps)
|
1188
|
-
migrator = Migrator.new(direction, migrations, schema_migration)
|
1379
|
+
migrator = Migrator.new(direction, migrations, schema_migration, internal_metadata)
|
1189
1380
|
|
1190
1381
|
if current_version != 0 && !migrator.current_migration
|
1191
1382
|
raise UnknownMigrationVersionError.new(current_version)
|
@@ -1210,23 +1401,28 @@ module ActiveRecord
|
|
1210
1401
|
|
1211
1402
|
# For cases where a table doesn't exist like loading from schema cache
|
1212
1403
|
def current_version
|
1213
|
-
|
1404
|
+
connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
1405
|
+
schema_migration = SchemaMigration.new(connection)
|
1406
|
+
internal_metadata = InternalMetadata.new(connection)
|
1407
|
+
|
1408
|
+
MigrationContext.new(migrations_paths, schema_migration, internal_metadata).current_version
|
1214
1409
|
end
|
1215
1410
|
end
|
1216
1411
|
|
1217
1412
|
self.migrations_paths = ["db/migrate"]
|
1218
1413
|
|
1219
|
-
def initialize(direction, migrations, schema_migration, target_version = nil)
|
1414
|
+
def initialize(direction, migrations, schema_migration, internal_metadata, target_version = nil)
|
1220
1415
|
@direction = direction
|
1221
1416
|
@target_version = target_version
|
1222
1417
|
@migrated_versions = nil
|
1223
1418
|
@migrations = migrations
|
1224
1419
|
@schema_migration = schema_migration
|
1420
|
+
@internal_metadata = internal_metadata
|
1225
1421
|
|
1226
1422
|
validate(@migrations)
|
1227
1423
|
|
1228
1424
|
@schema_migration.create_table
|
1229
|
-
|
1425
|
+
@internal_metadata.create_table
|
1230
1426
|
end
|
1231
1427
|
|
1232
1428
|
def current_version
|
@@ -1279,18 +1475,21 @@ module ActiveRecord
|
|
1279
1475
|
end
|
1280
1476
|
|
1281
1477
|
def load_migrated
|
1282
|
-
@migrated_versions = Set.new(@schema_migration.
|
1478
|
+
@migrated_versions = Set.new(@schema_migration.integer_versions)
|
1283
1479
|
end
|
1284
1480
|
|
1285
1481
|
private
|
1482
|
+
def connection
|
1483
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
1484
|
+
end
|
1485
|
+
|
1286
1486
|
# Used for running a specific migration.
|
1287
1487
|
def run_without_lock
|
1288
1488
|
migration = migrations.detect { |m| m.version == @target_version }
|
1289
1489
|
raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
|
1290
|
-
result = execute_migration_in_transaction(migration)
|
1291
1490
|
|
1292
1491
|
record_environment
|
1293
|
-
|
1492
|
+
execute_migration_in_transaction(migration)
|
1294
1493
|
end
|
1295
1494
|
|
1296
1495
|
# Used for running multiple migrations up to or down to a certain value.
|
@@ -1299,15 +1498,15 @@ module ActiveRecord
|
|
1299
1498
|
raise UnknownMigrationVersionError.new(@target_version)
|
1300
1499
|
end
|
1301
1500
|
|
1302
|
-
result = runnable.each(&method(:execute_migration_in_transaction))
|
1303
1501
|
record_environment
|
1304
|
-
|
1502
|
+
runnable.each(&method(:execute_migration_in_transaction))
|
1305
1503
|
end
|
1306
1504
|
|
1307
1505
|
# Stores the current environment in the database.
|
1308
1506
|
def record_environment
|
1309
1507
|
return if down?
|
1310
|
-
|
1508
|
+
|
1509
|
+
@internal_metadata[:environment] = connection.pool.db_config.env_name
|
1311
1510
|
end
|
1312
1511
|
|
1313
1512
|
def ran?(migration)
|
@@ -1359,10 +1558,10 @@ module ActiveRecord
|
|
1359
1558
|
def record_version_state_after_migrating(version)
|
1360
1559
|
if down?
|
1361
1560
|
migrated.delete(version)
|
1362
|
-
@schema_migration.
|
1561
|
+
@schema_migration.delete_version(version.to_s)
|
1363
1562
|
else
|
1364
1563
|
migrated << version
|
1365
|
-
@schema_migration.
|
1564
|
+
@schema_migration.create_version(version.to_s)
|
1366
1565
|
end
|
1367
1566
|
end
|
1368
1567
|
|
@@ -1375,52 +1574,40 @@ module ActiveRecord
|
|
1375
1574
|
end
|
1376
1575
|
|
1377
1576
|
# Wrap the migration in a transaction only if supported by the adapter.
|
1378
|
-
def ddl_transaction(migration)
|
1577
|
+
def ddl_transaction(migration, &block)
|
1379
1578
|
if use_transaction?(migration)
|
1380
|
-
|
1579
|
+
connection.transaction(&block)
|
1381
1580
|
else
|
1382
1581
|
yield
|
1383
1582
|
end
|
1384
1583
|
end
|
1385
1584
|
|
1386
1585
|
def use_transaction?(migration)
|
1387
|
-
!migration.disable_ddl_transaction &&
|
1586
|
+
!migration.disable_ddl_transaction && connection.supports_ddl_transactions?
|
1388
1587
|
end
|
1389
1588
|
|
1390
1589
|
def use_advisory_lock?
|
1391
|
-
|
1590
|
+
connection.advisory_locks_enabled?
|
1392
1591
|
end
|
1393
1592
|
|
1394
1593
|
def with_advisory_lock
|
1395
1594
|
lock_id = generate_migrator_advisory_lock_id
|
1396
1595
|
|
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) }
|
1596
|
+
got_lock = connection.get_advisory_lock(lock_id)
|
1597
|
+
raise ConcurrentMigrationError unless got_lock
|
1598
|
+
load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
|
1599
|
+
yield
|
1417
1600
|
ensure
|
1418
|
-
|
1601
|
+
if got_lock && !connection.release_advisory_lock(lock_id)
|
1602
|
+
raise ConcurrentMigrationError.new(
|
1603
|
+
ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
|
1604
|
+
)
|
1605
|
+
end
|
1419
1606
|
end
|
1420
1607
|
|
1421
1608
|
MIGRATOR_SALT = 2053462845
|
1422
1609
|
def generate_migrator_advisory_lock_id
|
1423
|
-
db_name_hash = Zlib.crc32(
|
1610
|
+
db_name_hash = Zlib.crc32(connection.current_database)
|
1424
1611
|
MIGRATOR_SALT * db_name_hash
|
1425
1612
|
end
|
1426
1613
|
end
|