activerecord 6.0.0 → 7.2.3
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 +996 -594
- data/MIT-LICENSE +1 -1
- data/README.rdoc +34 -34
- data/examples/performance.rb +2 -2
- data/lib/active_record/aggregations.rb +22 -20
- data/lib/active_record/association_relation.rb +22 -12
- data/lib/active_record/associations/alias_tracker.rb +41 -30
- data/lib/active_record/associations/association.rb +106 -41
- data/lib/active_record/associations/association_scope.rb +30 -21
- data/lib/active_record/associations/belongs_to_association.rb +69 -14
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +20 -6
- data/lib/active_record/associations/builder/association.rb +39 -6
- data/lib/active_record/associations/builder/belongs_to.rb +47 -17
- data/lib/active_record/associations/builder/collection_association.rb +14 -6
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -10
- data/lib/active_record/associations/builder/has_many.rb +7 -3
- data/lib/active_record/associations/builder/has_one.rb +13 -16
- data/lib/active_record/associations/builder/singular_association.rb +7 -3
- data/lib/active_record/associations/collection_association.rb +90 -53
- data/lib/active_record/associations/collection_proxy.rb +54 -19
- 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 +21 -1
- data/lib/active_record/associations/has_many_association.rb +41 -10
- data/lib/active_record/associations/has_many_through_association.rb +29 -12
- data/lib/active_record/associations/has_one_association.rb +33 -9
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +41 -17
- data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
- data/lib/active_record/associations/join_dependency.rb +97 -54
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +237 -54
- 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 +51 -17
- data/lib/active_record/associations/preloader.rb +55 -121
- data/lib/active_record/associations/singular_association.rb +16 -4
- data/lib/active_record/associations/through_association.rb +26 -15
- data/lib/active_record/associations.rb +454 -440
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +11 -14
- data/lib/active_record/attribute_methods/before_type_cast.rb +36 -11
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +75 -34
- data/lib/active_record/attribute_methods/primary_key.rb +53 -31
- data/lib/active_record/attribute_methods/query.rb +31 -22
- data/lib/active_record/attribute_methods/read.rb +16 -17
- data/lib/active_record/attribute_methods/serialization.rb +177 -35
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +18 -15
- data/lib/active_record/attribute_methods/write.rb +16 -28
- data/lib/active_record/attribute_methods.rb +227 -100
- data/lib/active_record/attributes.rb +94 -56
- data/lib/active_record/autosave_association.rb +119 -73
- data/lib/active_record/base.rb +31 -21
- data/lib/active_record/callbacks.rb +168 -55
- 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 -25
- 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 +367 -565
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -57
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +277 -89
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +241 -69
- data/lib/active_record/connection_adapters/abstract/quoting.rb +122 -134
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -116
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +324 -72
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +17 -4
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +611 -211
- data/lib/active_record/connection_adapters/abstract/transaction.rb +425 -82
- data/lib/active_record/connection_adapters/abstract_adapter.rb +698 -211
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +464 -239
- data/lib/active_record/connection_adapters/column.rb +28 -1
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +32 -137
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +90 -43
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +41 -7
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +18 -1
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +13 -4
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +53 -15
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +127 -63
- data/lib/active_record/connection_adapters/pool_config.rb +83 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +57 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +54 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +127 -100
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +9 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +15 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -15
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +5 -4
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +35 -8
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- 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 +23 -4
- data/lib/active_record/connection_adapters/postgresql/oid.rb +4 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +139 -106
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +98 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +176 -4
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +462 -118
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -11
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +585 -295
- data/lib/active_record/connection_adapters/schema_cache.rb +399 -60
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +8 -0
- data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +99 -48
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +80 -54
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +27 -1
- 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 +102 -24
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +425 -174
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -1
- 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 +176 -0
- data/lib/active_record/connection_handling.rb +243 -115
- data/lib/active_record/core.rb +481 -199
- data/lib/active_record/counter_cache.rb +69 -32
- data/lib/active_record/database_configurations/connection_url_resolver.rb +107 -0
- data/lib/active_record/database_configurations/database_config.rb +77 -10
- data/lib/active_record/database_configurations/hash_config.rb +148 -26
- data/lib/active_record/database_configurations/url_config.rb +44 -45
- data/lib/active_record/database_configurations.rb +190 -114
- data/lib/active_record/delegated_type.rb +279 -0
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +38 -0
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +5 -6
- 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 +171 -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 +58 -0
- data/lib/active_record/enum.rb +224 -73
- data/lib/active_record/errors.rb +254 -36
- data/lib/active_record/explain.rb +30 -17
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/explain_subscriber.rb +2 -2
- data/lib/active_record/fixture_set/file.rb +22 -15
- data/lib/active_record/fixture_set/model_metadata.rb +15 -6
- data/lib/active_record/fixture_set/render_context.rb +3 -1
- data/lib/active_record/fixture_set/table_row.rb +88 -16
- data/lib/active_record/fixture_set/table_rows.rb +4 -5
- data/lib/active_record/fixtures.rb +229 -116
- data/lib/active_record/future_result.rb +178 -0
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +121 -48
- data/lib/active_record/insert_all.rb +178 -29
- data/lib/active_record/integration.rb +16 -14
- data/lib/active_record/internal_metadata.rb +132 -21
- data/lib/active_record/legacy_yaml_adapter.rb +3 -36
- data/lib/active_record/locking/optimistic.rb +64 -33
- data/lib/active_record/locking/pessimistic.rb +21 -8
- data/lib/active_record/log_subscriber.rb +61 -30
- data/lib/active_record/marshalling.rb +59 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +19 -19
- data/lib/active_record/middleware/database_selector.rb +25 -13
- data/lib/active_record/middleware/shard_selector.rb +62 -0
- data/lib/active_record/migration/command_recorder.rb +160 -55
- data/lib/active_record/migration/compatibility.rb +286 -43
- 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 -2
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +421 -193
- data/lib/active_record/model_schema.rb +217 -125
- data/lib/active_record/nested_attributes.rb +62 -27
- data/lib/active_record/no_touching.rb +4 -4
- data/lib/active_record/normalization.rb +163 -0
- data/lib/active_record/persistence.rb +322 -319
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +18 -15
- data/lib/active_record/query_logs.rb +193 -0
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +54 -14
- data/lib/active_record/railtie.rb +250 -72
- data/lib/active_record/railties/console_sandbox.rb +2 -4
- data/lib/active_record/railties/controller_runtime.rb +25 -11
- data/lib/active_record/railties/databases.rake +312 -197
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +45 -3
- data/lib/active_record/reflection.rb +389 -146
- data/lib/active_record/relation/batches/batch_enumerator.rb +61 -16
- data/lib/active_record/relation/batches.rb +214 -73
- data/lib/active_record/relation/calculations.rb +379 -124
- data/lib/active_record/relation/delegation.rb +36 -23
- data/lib/active_record/relation/finder_methods.rb +159 -49
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +41 -33
- data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -11
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -7
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +20 -13
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +79 -53
- data/lib/active_record/relation/query_attribute.rb +30 -12
- data/lib/active_record/relation/query_methods.rb +1156 -279
- data/lib/active_record/relation/record_fetch_warning.rb +12 -11
- data/lib/active_record/relation/spawn_methods.rb +10 -9
- data/lib/active_record/relation/where_clause.rb +100 -66
- data/lib/active_record/relation.rb +829 -194
- data/lib/active_record/result.rb +76 -56
- data/lib/active_record/runtime_registry.rb +71 -13
- data/lib/active_record/sanitization.rb +86 -47
- data/lib/active_record/schema.rb +39 -23
- data/lib/active_record/schema_dumper.rb +140 -33
- data/lib/active_record/schema_migration.rb +74 -29
- data/lib/active_record/scoping/default.rb +73 -19
- data/lib/active_record/scoping/named.rb +10 -28
- data/lib/active_record/scoping.rb +65 -35
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +34 -8
- data/lib/active_record/serialization.rb +11 -4
- data/lib/active_record/signed_id.rb +138 -0
- data/lib/active_record/statement_cache.rb +26 -10
- data/lib/active_record/store.rb +19 -14
- data/lib/active_record/suppressor.rb +15 -17
- data/lib/active_record/table_metadata.rb +46 -36
- data/lib/active_record/tasks/database_tasks.rb +371 -205
- data/lib/active_record/tasks/mysql_database_tasks.rb +43 -36
- data/lib/active_record/tasks/postgresql_database_tasks.rb +54 -41
- data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -13
- data/lib/active_record/test_databases.rb +5 -4
- data/lib/active_record/test_fixtures.rb +189 -104
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +35 -25
- data/lib/active_record/token_for.rb +123 -0
- data/lib/active_record/touch_later.rb +31 -27
- data/lib/active_record/transaction.rb +132 -0
- data/lib/active_record/transactions.rb +131 -99
- data/lib/active_record/translation.rb +3 -5
- data/lib/active_record/type/adapter_specific_registry.rb +33 -18
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -2
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +11 -6
- data/lib/active_record/type/time.rb +14 -0
- data/lib/active_record/type/type_map.rb +17 -21
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type.rb +7 -2
- data/lib/active_record/type_caster/connection.rb +4 -5
- data/lib/active_record/type_caster/map.rb +8 -5
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +13 -8
- data/lib/active_record/validations/numericality.rb +36 -0
- data/lib/active_record/validations/presence.rb +5 -28
- data/lib/active_record/validations/uniqueness.rb +88 -18
- data/lib/active_record/validations.rb +15 -8
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +446 -40
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/attributes/attribute.rb +4 -8
- data/lib/arel/collectors/bind.rb +8 -1
- data/lib/arel/collectors/composite.rb +15 -0
- data/lib/arel/collectors/sql_string.rb +7 -0
- data/lib/arel/collectors/substitute_binds.rb +7 -0
- data/lib/arel/crud.rb +30 -22
- data/lib/arel/delete_manager.rb +23 -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 +82 -9
- data/lib/arel/nodes/bind_param.rb +8 -0
- data/lib/arel/nodes/bound_sql_literal.rb +65 -0
- data/lib/arel/nodes/casted.rb +22 -10
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/delete_statement.rb +14 -13
- data/lib/arel/nodes/equality.rb +6 -9
- 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/grouping.rb +3 -0
- data/lib/arel/nodes/homogeneous_in.rb +68 -0
- data/lib/arel/nodes/in.rb +8 -1
- data/lib/arel/nodes/infix_operation.rb +13 -1
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/join_source.rb +1 -1
- 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 +122 -11
- data/lib/arel/nodes/ordering.rb +27 -0
- 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 +16 -0
- data/lib/arel/nodes/table_alias.rb +11 -3
- data/lib/arel/nodes/unary.rb +0 -1
- data/lib/arel/nodes/update_statement.rb +11 -4
- data/lib/arel/nodes.rb +10 -3
- data/lib/arel/predications.rb +31 -28
- data/lib/arel/select_manager.rb +18 -9
- data/lib/arel/table.rb +21 -10
- data/lib/arel/tree_manager.rb +8 -15
- data/lib/arel/update_manager.rb +25 -5
- data/lib/arel/visitors/dot.rb +94 -90
- data/lib/arel/visitors/mysql.rb +34 -6
- data/lib/arel/visitors/postgresql.rb +5 -16
- data/lib/arel/visitors/sqlite.rb +25 -1
- data/lib/arel/visitors/to_sql.rb +227 -81
- data/lib/arel/visitors/visitor.rb +2 -3
- data/lib/arel/visitors.rb +0 -7
- data/lib/arel.rb +37 -15
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +6 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
- data/lib/rails/generators/active_record/migration.rb +9 -3
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +49 -4
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- 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 +117 -30
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/null_relation.rb +0 -68
- data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
- data/lib/active_record/relation/where_clause_factory.rb +0 -33
- data/lib/arel/attributes.rb +0 -22
- data/lib/arel/visitors/depth_first.rb +0 -204
- data/lib/arel/visitors/ibm_db.rb +0 -34
- data/lib/arel/visitors/informix.rb +0 -62
- data/lib/arel/visitors/mssql.rb +0 -157
- data/lib/arel/visitors/oracle.rb +0 -159
- data/lib/arel/visitors/oracle12.rb +0 -66
- data/lib/arel/visitors/where_sql.rb +0 -23
|
@@ -3,11 +3,14 @@
|
|
|
3
3
|
require "benchmark"
|
|
4
4
|
require "set"
|
|
5
5
|
require "zlib"
|
|
6
|
+
require "active_support/core_ext/array/access"
|
|
7
|
+
require "active_support/core_ext/enumerable"
|
|
6
8
|
require "active_support/core_ext/module/attribute_accessors"
|
|
7
9
|
require "active_support/actionable_error"
|
|
10
|
+
require "active_record/migration/pending_migration_connection"
|
|
8
11
|
|
|
9
12
|
module ActiveRecord
|
|
10
|
-
class MigrationError < ActiveRecordError
|
|
13
|
+
class MigrationError < ActiveRecordError # :nodoc:
|
|
11
14
|
def initialize(message = nil)
|
|
12
15
|
message = "\n\n#{message}\n\n" if message
|
|
13
16
|
super
|
|
@@ -18,7 +21,7 @@ module ActiveRecord
|
|
|
18
21
|
# For example the following migration is not reversible.
|
|
19
22
|
# Rolling back this migration will raise an ActiveRecord::IrreversibleMigration error.
|
|
20
23
|
#
|
|
21
|
-
# class IrreversibleMigrationExample < ActiveRecord::Migration[
|
|
24
|
+
# class IrreversibleMigrationExample < ActiveRecord::Migration[7.2]
|
|
22
25
|
# def change
|
|
23
26
|
# create_table :distributors do |t|
|
|
24
27
|
# t.string :zipcode
|
|
@@ -36,7 +39,7 @@ module ActiveRecord
|
|
|
36
39
|
#
|
|
37
40
|
# 1. Define <tt>#up</tt> and <tt>#down</tt> methods instead of <tt>#change</tt>:
|
|
38
41
|
#
|
|
39
|
-
# class ReversibleMigrationExample < ActiveRecord::Migration[
|
|
42
|
+
# class ReversibleMigrationExample < ActiveRecord::Migration[7.2]
|
|
40
43
|
# def up
|
|
41
44
|
# create_table :distributors do |t|
|
|
42
45
|
# t.string :zipcode
|
|
@@ -61,7 +64,7 @@ module ActiveRecord
|
|
|
61
64
|
#
|
|
62
65
|
# 2. Use the #reversible method in <tt>#change</tt> method:
|
|
63
66
|
#
|
|
64
|
-
# class ReversibleMigrationExample < ActiveRecord::Migration[
|
|
67
|
+
# class ReversibleMigrationExample < ActiveRecord::Migration[7.2]
|
|
65
68
|
# def change
|
|
66
69
|
# create_table :distributors do |t|
|
|
67
70
|
# t.string :zipcode
|
|
@@ -88,7 +91,7 @@ module ActiveRecord
|
|
|
88
91
|
class IrreversibleMigration < MigrationError
|
|
89
92
|
end
|
|
90
93
|
|
|
91
|
-
class DuplicateMigrationVersionError < MigrationError
|
|
94
|
+
class DuplicateMigrationVersionError < MigrationError # :nodoc:
|
|
92
95
|
def initialize(version = nil)
|
|
93
96
|
if version
|
|
94
97
|
super("Multiple migrations have the version number #{version}.")
|
|
@@ -98,7 +101,7 @@ module ActiveRecord
|
|
|
98
101
|
end
|
|
99
102
|
end
|
|
100
103
|
|
|
101
|
-
class DuplicateMigrationNameError < MigrationError
|
|
104
|
+
class DuplicateMigrationNameError < MigrationError # :nodoc:
|
|
102
105
|
def initialize(name = nil)
|
|
103
106
|
if name
|
|
104
107
|
super("Multiple migrations have the name #{name}.")
|
|
@@ -108,7 +111,7 @@ module ActiveRecord
|
|
|
108
111
|
end
|
|
109
112
|
end
|
|
110
113
|
|
|
111
|
-
class UnknownMigrationVersionError < MigrationError
|
|
114
|
+
class UnknownMigrationVersionError < MigrationError # :nodoc:
|
|
112
115
|
def initialize(version = nil)
|
|
113
116
|
if version
|
|
114
117
|
super("No migration with version number #{version}.")
|
|
@@ -118,7 +121,7 @@ module ActiveRecord
|
|
|
118
121
|
end
|
|
119
122
|
end
|
|
120
123
|
|
|
121
|
-
class IllegalMigrationNameError < MigrationError
|
|
124
|
+
class IllegalMigrationNameError < MigrationError # :nodoc:
|
|
122
125
|
def initialize(name = nil)
|
|
123
126
|
if name
|
|
124
127
|
super("Illegal name for migration file: #{name}\n\t(only lower case letters, numbers, and '_' allowed).")
|
|
@@ -128,25 +131,63 @@ module ActiveRecord
|
|
|
128
131
|
end
|
|
129
132
|
end
|
|
130
133
|
|
|
131
|
-
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:
|
|
132
151
|
include ActiveSupport::ActionableError
|
|
133
152
|
|
|
134
153
|
action "Run pending migrations" do
|
|
135
154
|
ActiveRecord::Tasks::DatabaseTasks.migrate
|
|
155
|
+
|
|
156
|
+
if ActiveRecord.dump_schema_after_migration
|
|
157
|
+
connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
|
158
|
+
ActiveRecord::Tasks::DatabaseTasks.dump_schema(connection.pool.db_config)
|
|
159
|
+
end
|
|
136
160
|
end
|
|
137
161
|
|
|
138
|
-
def initialize(message = nil)
|
|
139
|
-
if
|
|
140
|
-
|
|
141
|
-
elsif !message
|
|
142
|
-
super("Migrations are pending. To resolve this issue, run:\n\n rails db:migrate")
|
|
143
|
-
else
|
|
144
|
-
super
|
|
162
|
+
def initialize(message = nil, pending_migrations: nil)
|
|
163
|
+
if pending_migrations.nil?
|
|
164
|
+
pending_migrations = connection_pool.migration_context.open.pending_migrations
|
|
145
165
|
end
|
|
166
|
+
|
|
167
|
+
super(message || detailed_migration_message(pending_migrations))
|
|
146
168
|
end
|
|
169
|
+
|
|
170
|
+
private
|
|
171
|
+
def detailed_migration_message(pending_migrations)
|
|
172
|
+
message = "Migrations are pending. To resolve this issue, run:\n\n bin/rails db:migrate"
|
|
173
|
+
message += " RAILS_ENV=#{::Rails.env}" if defined?(Rails.env) && !Rails.env.local?
|
|
174
|
+
message += "\n\n"
|
|
175
|
+
|
|
176
|
+
message += "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}\n\n"
|
|
177
|
+
|
|
178
|
+
pending_migrations.each do |pending_migration|
|
|
179
|
+
message += "#{pending_migration.filename}\n"
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
message
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def connection_pool
|
|
186
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool
|
|
187
|
+
end
|
|
147
188
|
end
|
|
148
189
|
|
|
149
|
-
class ConcurrentMigrationError < MigrationError
|
|
190
|
+
class ConcurrentMigrationError < MigrationError # :nodoc:
|
|
150
191
|
DEFAULT_MESSAGE = "Cannot run migrations because another migration process is currently running."
|
|
151
192
|
RELEASE_LOCK_FAILED_MESSAGE = "Failed to release advisory lock"
|
|
152
193
|
|
|
@@ -155,9 +196,9 @@ module ActiveRecord
|
|
|
155
196
|
end
|
|
156
197
|
end
|
|
157
198
|
|
|
158
|
-
class NoEnvironmentInSchemaError < MigrationError
|
|
199
|
+
class NoEnvironmentInSchemaError < MigrationError # :nodoc:
|
|
159
200
|
def initialize
|
|
160
|
-
msg = "Environment data not found in the schema. To resolve this issue, run: \n\n rails db:environment:set"
|
|
201
|
+
msg = "Environment data not found in the schema. To resolve this issue, run: \n\n bin/rails db:environment:set"
|
|
161
202
|
if defined?(Rails.env)
|
|
162
203
|
super("#{msg} RAILS_ENV=#{::Rails.env}")
|
|
163
204
|
else
|
|
@@ -166,7 +207,7 @@ module ActiveRecord
|
|
|
166
207
|
end
|
|
167
208
|
end
|
|
168
209
|
|
|
169
|
-
class ProtectedEnvironmentError < ActiveRecordError
|
|
210
|
+
class ProtectedEnvironmentError < ActiveRecordError # :nodoc:
|
|
170
211
|
def initialize(env = "production")
|
|
171
212
|
msg = +"You are attempting to run a destructive action against your '#{env}' database.\n"
|
|
172
213
|
msg << "If you are sure you want to continue, run the same command with the environment variable:\n"
|
|
@@ -180,7 +221,7 @@ module ActiveRecord
|
|
|
180
221
|
msg = +"You are attempting to modify a database that was last run in `#{ stored }` environment.\n"
|
|
181
222
|
msg << "You are running in `#{ current }` environment. "
|
|
182
223
|
msg << "If you are sure you want to continue, first set the environment using:\n\n"
|
|
183
|
-
msg << " rails db:environment:set"
|
|
224
|
+
msg << " bin/rails db:environment:set"
|
|
184
225
|
if defined?(Rails.env)
|
|
185
226
|
super("#{msg} RAILS_ENV=#{::Rails.env}\n\n")
|
|
186
227
|
else
|
|
@@ -189,6 +230,14 @@ module ActiveRecord
|
|
|
189
230
|
end
|
|
190
231
|
end
|
|
191
232
|
|
|
233
|
+
class EnvironmentStorageError < ActiveRecordError # :nodoc:
|
|
234
|
+
def initialize
|
|
235
|
+
msg = +"You are attempting to store the environment in a database where metadata is disabled.\n"
|
|
236
|
+
msg << "Check your database configuration to see if this is intended."
|
|
237
|
+
super(msg)
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
192
241
|
# = Active Record Migrations
|
|
193
242
|
#
|
|
194
243
|
# Migrations can manage the evolution of a schema used by several physical
|
|
@@ -201,7 +250,7 @@ module ActiveRecord
|
|
|
201
250
|
#
|
|
202
251
|
# Example of a simple migration:
|
|
203
252
|
#
|
|
204
|
-
# class AddSsl < ActiveRecord::Migration[
|
|
253
|
+
# class AddSsl < ActiveRecord::Migration[7.2]
|
|
205
254
|
# def up
|
|
206
255
|
# add_column :accounts, :ssl_enabled, :boolean, default: true
|
|
207
256
|
# end
|
|
@@ -221,7 +270,7 @@ module ActiveRecord
|
|
|
221
270
|
#
|
|
222
271
|
# Example of a more complex migration that also needs to initialize data:
|
|
223
272
|
#
|
|
224
|
-
# class AddSystemSettings < ActiveRecord::Migration[
|
|
273
|
+
# class AddSystemSettings < ActiveRecord::Migration[7.2]
|
|
225
274
|
# def up
|
|
226
275
|
# create_table :system_settings do |t|
|
|
227
276
|
# t.string :name
|
|
@@ -293,13 +342,13 @@ module ActiveRecord
|
|
|
293
342
|
# +table_name+. Passing a hash containing <tt>:from</tt> and <tt>:to</tt>
|
|
294
343
|
# as +default_or_changes+ will make this change reversible in the migration.
|
|
295
344
|
# * <tt>change_column_null(table_name, column_name, null, default = nil)</tt>:
|
|
296
|
-
# Sets or removes a
|
|
345
|
+
# Sets or removes a <tt>NOT NULL</tt> constraint on +column_name+. The +null+ flag
|
|
297
346
|
# indicates whether the value can be +NULL+. See
|
|
298
347
|
# ActiveRecord::ConnectionAdapters::SchemaStatements#change_column_null for
|
|
299
348
|
# details.
|
|
300
349
|
# * <tt>change_table(name, options)</tt>: Allows to make column alterations to
|
|
301
350
|
# the table called +name+. It makes the table object available to a block that
|
|
302
|
-
# can then add/remove columns, indexes or foreign keys to it.
|
|
351
|
+
# can then add/remove columns, indexes, or foreign keys to it.
|
|
303
352
|
# * <tt>rename_column(table_name, column_name, new_column_name)</tt>: Renames
|
|
304
353
|
# a column but keeps the type and content.
|
|
305
354
|
# * <tt>rename_index(table_name, old_name, new_name)</tt>: Renames an index.
|
|
@@ -329,15 +378,16 @@ module ActiveRecord
|
|
|
329
378
|
# == Irreversible transformations
|
|
330
379
|
#
|
|
331
380
|
# Some transformations are destructive in a manner that cannot be reversed.
|
|
332
|
-
# Migrations of that kind should raise an
|
|
381
|
+
# Migrations of that kind should raise an ActiveRecord::IrreversibleMigration
|
|
333
382
|
# exception in their +down+ method.
|
|
334
383
|
#
|
|
335
|
-
# == Running migrations from within Rails
|
|
384
|
+
# == Running migrations from within \Rails
|
|
336
385
|
#
|
|
337
|
-
# 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.
|
|
338
387
|
#
|
|
339
388
|
# To generate a new migration, you can use
|
|
340
|
-
#
|
|
389
|
+
#
|
|
390
|
+
# $ bin/rails generate migration MyNewMigration
|
|
341
391
|
#
|
|
342
392
|
# where MyNewMigration is the name of your migration. The generator will
|
|
343
393
|
# create an empty migration file <tt>timestamp_my_new_migration.rb</tt>
|
|
@@ -346,41 +396,36 @@ module ActiveRecord
|
|
|
346
396
|
#
|
|
347
397
|
# There is a special syntactic shortcut to generate migrations that add fields to a table.
|
|
348
398
|
#
|
|
349
|
-
# rails generate migration add_fieldname_to_tablename fieldname:string
|
|
399
|
+
# $ bin/rails generate migration add_fieldname_to_tablename fieldname:string
|
|
350
400
|
#
|
|
351
401
|
# This will generate the file <tt>timestamp_add_fieldname_to_tablename.rb</tt>, which will look like this:
|
|
352
|
-
# class AddFieldnameToTablename < ActiveRecord::Migration[
|
|
402
|
+
# class AddFieldnameToTablename < ActiveRecord::Migration[7.2]
|
|
353
403
|
# def change
|
|
354
404
|
# add_column :tablenames, :fieldname, :string
|
|
355
405
|
# end
|
|
356
406
|
# end
|
|
357
407
|
#
|
|
358
408
|
# To run migrations against the currently configured database, use
|
|
359
|
-
# <tt>rails db:migrate</tt>. This will update the database by running all of the
|
|
409
|
+
# <tt>bin/rails db:migrate</tt>. This will update the database by running all of the
|
|
360
410
|
# pending migrations, creating the <tt>schema_migrations</tt> table
|
|
361
411
|
# (see "About the schema_migrations table" section below) if missing. It will also
|
|
362
412
|
# invoke the db:schema:dump command, which will update your db/schema.rb file
|
|
363
413
|
# to match the structure of your database.
|
|
364
414
|
#
|
|
365
415
|
# To roll the database back to a previous migration version, use
|
|
366
|
-
# <tt>rails db:rollback VERSION=X</tt> where <tt>X</tt> is the version to which
|
|
416
|
+
# <tt>bin/rails db:rollback VERSION=X</tt> where <tt>X</tt> is the version to which
|
|
367
417
|
# you wish to downgrade. Alternatively, you can also use the STEP option if you
|
|
368
|
-
# wish to rollback last few migrations. <tt>rails db:rollback STEP=2</tt> will rollback
|
|
418
|
+
# wish to rollback last few migrations. <tt>bin/rails db:rollback STEP=2</tt> will rollback
|
|
369
419
|
# the latest two migrations.
|
|
370
420
|
#
|
|
371
|
-
# If any of the migrations throw an
|
|
421
|
+
# If any of the migrations throw an ActiveRecord::IrreversibleMigration exception,
|
|
372
422
|
# that step will fail and you'll have some manual work to do.
|
|
373
423
|
#
|
|
374
|
-
# == Database support
|
|
375
|
-
#
|
|
376
|
-
# Migrations are currently supported in MySQL, PostgreSQL, SQLite,
|
|
377
|
-
# SQL Server, and Oracle (all supported databases except DB2).
|
|
378
|
-
#
|
|
379
424
|
# == More examples
|
|
380
425
|
#
|
|
381
426
|
# Not all migrations change the schema. Some just fix the data:
|
|
382
427
|
#
|
|
383
|
-
# class RemoveEmptyTags < ActiveRecord::Migration[
|
|
428
|
+
# class RemoveEmptyTags < ActiveRecord::Migration[7.2]
|
|
384
429
|
# def up
|
|
385
430
|
# Tag.all.each { |tag| tag.destroy if tag.pages.empty? }
|
|
386
431
|
# end
|
|
@@ -393,7 +438,7 @@ module ActiveRecord
|
|
|
393
438
|
#
|
|
394
439
|
# Others remove columns when they migrate up instead of down:
|
|
395
440
|
#
|
|
396
|
-
# class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[
|
|
441
|
+
# class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[7.2]
|
|
397
442
|
# def up
|
|
398
443
|
# remove_column :items, :incomplete_items_count
|
|
399
444
|
# remove_column :items, :completed_items_count
|
|
@@ -407,7 +452,7 @@ module ActiveRecord
|
|
|
407
452
|
#
|
|
408
453
|
# And sometimes you need to do something in SQL not abstracted directly by migrations:
|
|
409
454
|
#
|
|
410
|
-
# class MakeJoinUnique < ActiveRecord::Migration[
|
|
455
|
+
# class MakeJoinUnique < ActiveRecord::Migration[7.2]
|
|
411
456
|
# def up
|
|
412
457
|
# execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)"
|
|
413
458
|
# end
|
|
@@ -424,7 +469,7 @@ module ActiveRecord
|
|
|
424
469
|
# <tt>Base#reset_column_information</tt> in order to ensure that the model has the
|
|
425
470
|
# latest column data from after the new column was added. Example:
|
|
426
471
|
#
|
|
427
|
-
# class AddPeopleSalary < ActiveRecord::Migration[
|
|
472
|
+
# class AddPeopleSalary < ActiveRecord::Migration[7.2]
|
|
428
473
|
# def up
|
|
429
474
|
# add_column :people, :salary, :integer
|
|
430
475
|
# Person.reset_column_information
|
|
@@ -440,7 +485,7 @@ module ActiveRecord
|
|
|
440
485
|
# them to the console as they happen, along with benchmarks describing how
|
|
441
486
|
# long each step took.
|
|
442
487
|
#
|
|
443
|
-
# 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>.
|
|
444
489
|
#
|
|
445
490
|
# You can also insert your own messages and benchmarks by using the +say_with_time+
|
|
446
491
|
# method:
|
|
@@ -460,11 +505,15 @@ module ActiveRecord
|
|
|
460
505
|
#
|
|
461
506
|
# == Timestamped Migrations
|
|
462
507
|
#
|
|
463
|
-
# By default, Rails generates migrations that look like:
|
|
508
|
+
# By default, \Rails generates migrations that look like:
|
|
464
509
|
#
|
|
465
510
|
# 20080717013526_your_migration_name.rb
|
|
466
511
|
#
|
|
467
|
-
# 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
|
|
468
517
|
#
|
|
469
518
|
# If you'd prefer to use numeric prefixes, you can turn timestamped migrations
|
|
470
519
|
# off by setting:
|
|
@@ -482,7 +531,7 @@ module ActiveRecord
|
|
|
482
531
|
# To define a reversible migration, define the +change+ method in your
|
|
483
532
|
# migration like this:
|
|
484
533
|
#
|
|
485
|
-
# class TenderloveMigration < ActiveRecord::Migration[
|
|
534
|
+
# class TenderloveMigration < ActiveRecord::Migration[7.2]
|
|
486
535
|
# def change
|
|
487
536
|
# create_table(:horses) do |t|
|
|
488
537
|
# t.column :content, :text
|
|
@@ -499,11 +548,11 @@ module ActiveRecord
|
|
|
499
548
|
# as before.
|
|
500
549
|
#
|
|
501
550
|
# If a command cannot be reversed, an
|
|
502
|
-
#
|
|
551
|
+
# ActiveRecord::IrreversibleMigration exception will be raised when
|
|
503
552
|
# the migration is moving down.
|
|
504
553
|
#
|
|
505
554
|
# For a list of commands that are reversible, please see
|
|
506
|
-
#
|
|
555
|
+
# +ActiveRecord::Migration::CommandRecorder+.
|
|
507
556
|
#
|
|
508
557
|
# == Transactional Migrations
|
|
509
558
|
#
|
|
@@ -512,7 +561,7 @@ module ActiveRecord
|
|
|
512
561
|
# can't execute inside a transaction though, and for these situations
|
|
513
562
|
# you can turn the automatic transactions off.
|
|
514
563
|
#
|
|
515
|
-
# class ChangeEnum < ActiveRecord::Migration[
|
|
564
|
+
# class ChangeEnum < ActiveRecord::Migration[7.2]
|
|
516
565
|
# disable_ddl_transaction!
|
|
517
566
|
#
|
|
518
567
|
# def up
|
|
@@ -525,18 +574,58 @@ module ActiveRecord
|
|
|
525
574
|
class Migration
|
|
526
575
|
autoload :CommandRecorder, "active_record/migration/command_recorder"
|
|
527
576
|
autoload :Compatibility, "active_record/migration/compatibility"
|
|
577
|
+
autoload :JoinTable, "active_record/migration/join_table"
|
|
578
|
+
autoload :ExecutionStrategy, "active_record/migration/execution_strategy"
|
|
579
|
+
autoload :DefaultStrategy, "active_record/migration/default_strategy"
|
|
528
580
|
|
|
529
581
|
# This must be defined before the inherited hook, below
|
|
530
|
-
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
|
|
531
618
|
end
|
|
532
619
|
|
|
533
|
-
def self.inherited(subclass)
|
|
620
|
+
def self.inherited(subclass) # :nodoc:
|
|
534
621
|
super
|
|
535
622
|
if subclass.superclass == Migration
|
|
623
|
+
major = ActiveRecord::VERSION::MAJOR
|
|
624
|
+
minor = ActiveRecord::VERSION::MINOR
|
|
536
625
|
raise StandardError, "Directly inheriting from ActiveRecord::Migration is not supported. " \
|
|
537
|
-
"Please specify the
|
|
626
|
+
"Please specify the Active Record release the migration was written for:\n" \
|
|
538
627
|
"\n" \
|
|
539
|
-
" class #{subclass} < ActiveRecord::Migration[
|
|
628
|
+
" class #{subclass} < ActiveRecord::Migration[#{major}.#{minor}]"
|
|
540
629
|
end
|
|
541
630
|
end
|
|
542
631
|
|
|
@@ -548,76 +637,104 @@ module ActiveRecord
|
|
|
548
637
|
ActiveRecord::VERSION::STRING.to_f
|
|
549
638
|
end
|
|
550
639
|
|
|
551
|
-
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
|
|
552
648
|
|
|
553
649
|
# This class is used to verify that all migrations have been run before
|
|
554
|
-
# 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+.
|
|
555
651
|
class CheckPending
|
|
556
|
-
def initialize(app)
|
|
652
|
+
def initialize(app, file_watcher: ActiveSupport::FileUpdateChecker)
|
|
557
653
|
@app = app
|
|
558
|
-
@
|
|
654
|
+
@needs_check = true
|
|
655
|
+
@mutex = Mutex.new
|
|
656
|
+
@file_watcher = file_watcher
|
|
559
657
|
end
|
|
560
658
|
|
|
561
659
|
def call(env)
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
660
|
+
@mutex.synchronize do
|
|
661
|
+
@watcher ||= build_watcher do
|
|
662
|
+
@needs_check = true
|
|
663
|
+
ActiveRecord::Migration.check_pending_migrations
|
|
664
|
+
@needs_check = false
|
|
665
|
+
end
|
|
666
|
+
|
|
667
|
+
if @needs_check
|
|
668
|
+
@watcher.execute
|
|
669
|
+
else
|
|
670
|
+
@watcher.execute_if_updated
|
|
671
|
+
end
|
|
566
672
|
end
|
|
673
|
+
|
|
567
674
|
@app.call(env)
|
|
568
675
|
end
|
|
569
676
|
|
|
570
677
|
private
|
|
678
|
+
def build_watcher(&block)
|
|
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
|
|
682
|
+
@file_watcher.new([], paths.index_with(["rb"]), &block)
|
|
683
|
+
end
|
|
571
684
|
|
|
572
685
|
def connection
|
|
573
|
-
ActiveRecord::
|
|
686
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
|
574
687
|
end
|
|
575
688
|
end
|
|
576
689
|
|
|
577
690
|
class << self
|
|
578
|
-
attr_accessor :delegate
|
|
579
|
-
attr_accessor :disable_ddl_transaction
|
|
691
|
+
attr_accessor :delegate # :nodoc:
|
|
692
|
+
attr_accessor :disable_ddl_transaction # :nodoc:
|
|
580
693
|
|
|
581
|
-
def nearest_delegate
|
|
694
|
+
def nearest_delegate # :nodoc:
|
|
582
695
|
delegate || superclass.nearest_delegate
|
|
583
696
|
end
|
|
584
697
|
|
|
585
|
-
# Raises
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
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 = []
|
|
589
702
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
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
|
|
593
708
|
|
|
594
|
-
|
|
595
|
-
|
|
709
|
+
migrations = pending_migrations.flatten
|
|
710
|
+
|
|
711
|
+
if migrations.any?
|
|
712
|
+
raise ActiveRecord::PendingMigrationError.new(pending_migrations: migrations)
|
|
596
713
|
end
|
|
714
|
+
end
|
|
597
715
|
|
|
598
|
-
|
|
716
|
+
def load_schema_if_pending!
|
|
717
|
+
if any_schema_needs_update?
|
|
599
718
|
# Roundtrip to Rake to allow plugins to hook into database initialization.
|
|
600
719
|
root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
|
|
720
|
+
|
|
601
721
|
FileUtils.cd(root) do
|
|
602
|
-
Base.clear_all_connections!
|
|
722
|
+
Base.connection_handler.clear_all_connections!(:all)
|
|
603
723
|
system("bin/rails db:test:prepare")
|
|
604
724
|
end
|
|
605
725
|
end
|
|
606
726
|
|
|
607
|
-
|
|
608
|
-
Base.establish_connection(current_config)
|
|
609
|
-
|
|
610
|
-
check_pending!
|
|
727
|
+
check_pending_migrations
|
|
611
728
|
end
|
|
612
729
|
|
|
613
|
-
def maintain_test_schema!
|
|
614
|
-
if ActiveRecord
|
|
730
|
+
def maintain_test_schema! # :nodoc:
|
|
731
|
+
if ActiveRecord.maintain_test_schema
|
|
615
732
|
suppress_messages { load_schema_if_pending! }
|
|
616
733
|
end
|
|
617
734
|
end
|
|
618
735
|
|
|
619
|
-
def method_missing(name,
|
|
620
|
-
nearest_delegate.send(name,
|
|
736
|
+
def method_missing(name, ...) # :nodoc:
|
|
737
|
+
nearest_delegate.send(name, ...)
|
|
621
738
|
end
|
|
622
739
|
|
|
623
740
|
def migrate(direction)
|
|
@@ -631,12 +748,55 @@ module ActiveRecord
|
|
|
631
748
|
def disable_ddl_transaction!
|
|
632
749
|
@disable_ddl_transaction = true
|
|
633
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
|
|
634
788
|
end
|
|
635
789
|
|
|
636
|
-
def disable_ddl_transaction
|
|
790
|
+
def disable_ddl_transaction # :nodoc:
|
|
637
791
|
self.class.disable_ddl_transaction
|
|
638
792
|
end
|
|
639
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.
|
|
640
800
|
cattr_accessor :verbose
|
|
641
801
|
attr_accessor :name, :version
|
|
642
802
|
|
|
@@ -644,6 +804,11 @@ module ActiveRecord
|
|
|
644
804
|
@name = name
|
|
645
805
|
@version = version
|
|
646
806
|
@connection = nil
|
|
807
|
+
@pool = nil
|
|
808
|
+
end
|
|
809
|
+
|
|
810
|
+
def execution_strategy
|
|
811
|
+
@execution_strategy ||= ActiveRecord.migration_strategy.new(self)
|
|
647
812
|
end
|
|
648
813
|
|
|
649
814
|
self.verbose = true
|
|
@@ -657,7 +822,7 @@ module ActiveRecord
|
|
|
657
822
|
# and create the table 'apples' on the way up, and the reverse
|
|
658
823
|
# on the way down.
|
|
659
824
|
#
|
|
660
|
-
# class FixTLMigration < ActiveRecord::Migration[
|
|
825
|
+
# class FixTLMigration < ActiveRecord::Migration[7.2]
|
|
661
826
|
# def change
|
|
662
827
|
# revert do
|
|
663
828
|
# create_table(:horses) do |t|
|
|
@@ -674,9 +839,9 @@ module ActiveRecord
|
|
|
674
839
|
# Or equivalently, if +TenderloveMigration+ is defined as in the
|
|
675
840
|
# documentation for Migration:
|
|
676
841
|
#
|
|
677
|
-
# require_relative
|
|
842
|
+
# require_relative "20121212123456_tenderlove_migration"
|
|
678
843
|
#
|
|
679
|
-
# class FixupTLMigration < ActiveRecord::Migration[
|
|
844
|
+
# class FixupTLMigration < ActiveRecord::Migration[7.2]
|
|
680
845
|
# def change
|
|
681
846
|
# revert TenderloveMigration
|
|
682
847
|
#
|
|
@@ -687,16 +852,16 @@ module ActiveRecord
|
|
|
687
852
|
# end
|
|
688
853
|
#
|
|
689
854
|
# This command can be nested.
|
|
690
|
-
def revert(*migration_classes)
|
|
855
|
+
def revert(*migration_classes, &block)
|
|
691
856
|
run(*migration_classes.reverse, revert: true) unless migration_classes.empty?
|
|
692
857
|
if block_given?
|
|
693
858
|
if connection.respond_to? :revert
|
|
694
|
-
connection.revert
|
|
859
|
+
connection.revert(&block)
|
|
695
860
|
else
|
|
696
861
|
recorder = command_recorder
|
|
697
862
|
@connection = recorder
|
|
698
863
|
suppress_messages do
|
|
699
|
-
connection.revert
|
|
864
|
+
connection.revert(&block)
|
|
700
865
|
end
|
|
701
866
|
@connection = recorder.delegate
|
|
702
867
|
recorder.replay(self)
|
|
@@ -708,7 +873,7 @@ module ActiveRecord
|
|
|
708
873
|
connection.respond_to?(:reverting) && connection.reverting
|
|
709
874
|
end
|
|
710
875
|
|
|
711
|
-
ReversibleBlockHelper = Struct.new(:reverting) do
|
|
876
|
+
ReversibleBlockHelper = Struct.new(:reverting) do # :nodoc:
|
|
712
877
|
def up
|
|
713
878
|
yield unless reverting
|
|
714
879
|
end
|
|
@@ -727,7 +892,7 @@ module ActiveRecord
|
|
|
727
892
|
# when the three columns 'first_name', 'last_name' and 'full_name' exist,
|
|
728
893
|
# even when migrating down:
|
|
729
894
|
#
|
|
730
|
-
# class SplitNameMigration < ActiveRecord::Migration[
|
|
895
|
+
# class SplitNameMigration < ActiveRecord::Migration[7.2]
|
|
731
896
|
# def change
|
|
732
897
|
# add_column :users, :first_name, :string
|
|
733
898
|
# add_column :users, :last_name, :string
|
|
@@ -755,7 +920,7 @@ module ActiveRecord
|
|
|
755
920
|
# In the following example, the new column +published+ will be given
|
|
756
921
|
# the value +true+ for all existing records.
|
|
757
922
|
#
|
|
758
|
-
# class AddPublishedToPosts < ActiveRecord::Migration[
|
|
923
|
+
# class AddPublishedToPosts < ActiveRecord::Migration[7.2]
|
|
759
924
|
# def change
|
|
760
925
|
# add_column :posts, :published, :boolean, default: false
|
|
761
926
|
# up_only do
|
|
@@ -763,14 +928,15 @@ module ActiveRecord
|
|
|
763
928
|
# end
|
|
764
929
|
# end
|
|
765
930
|
# end
|
|
766
|
-
def up_only
|
|
767
|
-
execute_block
|
|
931
|
+
def up_only(&block)
|
|
932
|
+
execute_block(&block) unless reverting?
|
|
768
933
|
end
|
|
769
934
|
|
|
770
935
|
# Runs the given migration classes.
|
|
771
936
|
# Last argument can specify options:
|
|
772
|
-
#
|
|
773
|
-
# -
|
|
937
|
+
#
|
|
938
|
+
# - +:direction+ - Default is +:up+.
|
|
939
|
+
# - +:revert+ - Default is +false+.
|
|
774
940
|
def run(*migration_classes)
|
|
775
941
|
opts = migration_classes.extract_options!
|
|
776
942
|
dir = opts[:direction] || :up
|
|
@@ -807,7 +973,7 @@ module ActiveRecord
|
|
|
807
973
|
end
|
|
808
974
|
|
|
809
975
|
time = nil
|
|
810
|
-
ActiveRecord::
|
|
976
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection.pool.with_connection do |conn|
|
|
811
977
|
time = Benchmark.measure do
|
|
812
978
|
exec_migration(conn, direction)
|
|
813
979
|
end
|
|
@@ -828,10 +994,11 @@ module ActiveRecord
|
|
|
828
994
|
change
|
|
829
995
|
end
|
|
830
996
|
else
|
|
831
|
-
|
|
997
|
+
public_send(direction)
|
|
832
998
|
end
|
|
833
999
|
ensure
|
|
834
1000
|
@connection = nil
|
|
1001
|
+
@execution_strategy = nil
|
|
835
1002
|
end
|
|
836
1003
|
|
|
837
1004
|
def write(text = "")
|
|
@@ -870,37 +1037,41 @@ module ActiveRecord
|
|
|
870
1037
|
end
|
|
871
1038
|
|
|
872
1039
|
def connection
|
|
873
|
-
@connection || ActiveRecord::
|
|
1040
|
+
@connection || ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
|
874
1041
|
end
|
|
875
1042
|
|
|
876
|
-
def
|
|
877
|
-
|
|
1043
|
+
def connection_pool
|
|
1044
|
+
@pool || ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool
|
|
1045
|
+
end
|
|
878
1046
|
|
|
879
|
-
|
|
1047
|
+
def method_missing(method, *arguments, &block)
|
|
1048
|
+
say_with_time "#{method}(#{format_arguments(arguments)})" do
|
|
880
1049
|
unless connection.respond_to? :revert
|
|
881
1050
|
unless arguments.empty? || [:execute, :enable_extension, :disable_extension].include?(method)
|
|
882
1051
|
arguments[0] = proper_table_name(arguments.first, table_name_options)
|
|
883
|
-
if
|
|
1052
|
+
if method == :rename_table ||
|
|
884
1053
|
(method == :remove_foreign_key && !arguments.second.is_a?(Hash))
|
|
885
1054
|
arguments[1] = proper_table_name(arguments.second, table_name_options)
|
|
886
1055
|
end
|
|
887
1056
|
end
|
|
888
1057
|
end
|
|
889
|
-
return super unless
|
|
890
|
-
|
|
1058
|
+
return super unless execution_strategy.respond_to?(method)
|
|
1059
|
+
execution_strategy.send(method, *arguments, &block)
|
|
891
1060
|
end
|
|
892
1061
|
end
|
|
1062
|
+
ruby2_keywords(:method_missing)
|
|
893
1063
|
|
|
894
1064
|
def copy(destination, sources, options = {})
|
|
895
1065
|
copied = []
|
|
896
|
-
schema_migration = options[:schema_migration] || ActiveRecord::SchemaMigration
|
|
897
1066
|
|
|
898
1067
|
FileUtils.mkdir_p(destination) unless File.exist?(destination)
|
|
1068
|
+
schema_migration = SchemaMigration::NullSchemaMigration.new
|
|
1069
|
+
internal_metadata = InternalMetadata::NullInternalMetadata.new
|
|
899
1070
|
|
|
900
|
-
destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration).migrations
|
|
1071
|
+
destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration, internal_metadata).migrations
|
|
901
1072
|
last = destination_migrations.last
|
|
902
1073
|
sources.each do |scope, path|
|
|
903
|
-
source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration).migrations
|
|
1074
|
+
source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration, internal_metadata).migrations
|
|
904
1075
|
|
|
905
1076
|
source_migrations.each do |migration|
|
|
906
1077
|
source = File.binread(migration.filename)
|
|
@@ -915,6 +1086,12 @@ module ActiveRecord
|
|
|
915
1086
|
magic_comments << magic_comment; ""
|
|
916
1087
|
end || break
|
|
917
1088
|
end
|
|
1089
|
+
|
|
1090
|
+
if !magic_comments.empty? && source.start_with?("\n")
|
|
1091
|
+
magic_comments << "\n"
|
|
1092
|
+
source = source[1..-1]
|
|
1093
|
+
end
|
|
1094
|
+
|
|
918
1095
|
source = "#{magic_comments}#{inserted_comment}#{source}"
|
|
919
1096
|
|
|
920
1097
|
if duplicate = destination_migrations.detect { |m| m.name == migration.name }
|
|
@@ -952,16 +1129,16 @@ module ActiveRecord
|
|
|
952
1129
|
|
|
953
1130
|
# Determines the version number of the next migration.
|
|
954
1131
|
def next_migration_number(number)
|
|
955
|
-
if ActiveRecord
|
|
1132
|
+
if ActiveRecord.timestamped_migrations
|
|
956
1133
|
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max
|
|
957
1134
|
else
|
|
958
|
-
|
|
1135
|
+
"%.3d" % number.to_i
|
|
959
1136
|
end
|
|
960
1137
|
end
|
|
961
1138
|
|
|
962
1139
|
# Builds a hash for use in ActiveRecord::Migration#proper_table_name using
|
|
963
1140
|
# the Active Record object's table_name prefix and suffix
|
|
964
|
-
def table_name_options(config = ActiveRecord::Base)
|
|
1141
|
+
def table_name_options(config = ActiveRecord::Base) # :nodoc:
|
|
965
1142
|
{
|
|
966
1143
|
table_name_prefix: config.table_name_prefix,
|
|
967
1144
|
table_name_suffix: config.table_name_suffix
|
|
@@ -977,6 +1154,22 @@ module ActiveRecord
|
|
|
977
1154
|
end
|
|
978
1155
|
end
|
|
979
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
|
+
|
|
980
1173
|
def command_recorder
|
|
981
1174
|
CommandRecorder.new(connection)
|
|
982
1175
|
end
|
|
@@ -994,42 +1187,52 @@ module ActiveRecord
|
|
|
994
1187
|
File.basename(filename)
|
|
995
1188
|
end
|
|
996
1189
|
|
|
997
|
-
def mtime
|
|
998
|
-
File.mtime filename
|
|
999
|
-
end
|
|
1000
|
-
|
|
1001
1190
|
delegate :migrate, :announce, :write, :disable_ddl_transaction, to: :migration
|
|
1002
1191
|
|
|
1003
1192
|
private
|
|
1004
|
-
|
|
1005
1193
|
def migration
|
|
1006
1194
|
@migration ||= load_migration
|
|
1007
1195
|
end
|
|
1008
1196
|
|
|
1009
1197
|
def load_migration
|
|
1010
|
-
|
|
1198
|
+
Object.send(:remove_const, name) rescue nil
|
|
1199
|
+
|
|
1200
|
+
load(File.expand_path(filename))
|
|
1011
1201
|
name.constantize.new(name, version)
|
|
1012
1202
|
end
|
|
1013
1203
|
end
|
|
1014
1204
|
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
attr_reader :migrations_paths, :schema_migration
|
|
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
|
|
1027
1216
|
|
|
1028
|
-
def initialize(migrations_paths, schema_migration)
|
|
1217
|
+
def initialize(migrations_paths, schema_migration = nil, internal_metadata = nil)
|
|
1029
1218
|
@migrations_paths = migrations_paths
|
|
1030
|
-
@schema_migration = schema_migration
|
|
1219
|
+
@schema_migration = schema_migration || SchemaMigration.new(connection_pool)
|
|
1220
|
+
@internal_metadata = internal_metadata || InternalMetadata.new(connection_pool)
|
|
1031
1221
|
end
|
|
1032
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+.
|
|
1033
1236
|
def migrate(target_version = nil, &block)
|
|
1034
1237
|
case
|
|
1035
1238
|
when target_version.nil?
|
|
@@ -1043,71 +1246,70 @@ module ActiveRecord
|
|
|
1043
1246
|
end
|
|
1044
1247
|
end
|
|
1045
1248
|
|
|
1046
|
-
def rollback(steps = 1)
|
|
1249
|
+
def rollback(steps = 1) # :nodoc:
|
|
1047
1250
|
move(:down, steps)
|
|
1048
1251
|
end
|
|
1049
1252
|
|
|
1050
|
-
def forward(steps = 1)
|
|
1253
|
+
def forward(steps = 1) # :nodoc:
|
|
1051
1254
|
move(:up, steps)
|
|
1052
1255
|
end
|
|
1053
1256
|
|
|
1054
|
-
def up(target_version = nil)
|
|
1257
|
+
def up(target_version = nil, &block) # :nodoc:
|
|
1055
1258
|
selected_migrations = if block_given?
|
|
1056
|
-
migrations.select
|
|
1259
|
+
migrations.select(&block)
|
|
1057
1260
|
else
|
|
1058
1261
|
migrations
|
|
1059
1262
|
end
|
|
1060
1263
|
|
|
1061
|
-
Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate
|
|
1264
|
+
Migrator.new(:up, selected_migrations, schema_migration, internal_metadata, target_version).migrate
|
|
1062
1265
|
end
|
|
1063
1266
|
|
|
1064
|
-
def down(target_version = nil)
|
|
1267
|
+
def down(target_version = nil, &block) # :nodoc:
|
|
1065
1268
|
selected_migrations = if block_given?
|
|
1066
|
-
migrations.select
|
|
1269
|
+
migrations.select(&block)
|
|
1067
1270
|
else
|
|
1068
1271
|
migrations
|
|
1069
1272
|
end
|
|
1070
1273
|
|
|
1071
|
-
Migrator.new(:down, selected_migrations, schema_migration, target_version).migrate
|
|
1274
|
+
Migrator.new(:down, selected_migrations, schema_migration, internal_metadata, target_version).migrate
|
|
1072
1275
|
end
|
|
1073
1276
|
|
|
1074
|
-
def run(direction, target_version)
|
|
1075
|
-
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
|
|
1076
1279
|
end
|
|
1077
1280
|
|
|
1078
|
-
def open
|
|
1079
|
-
Migrator.new(:up, migrations, schema_migration)
|
|
1281
|
+
def open # :nodoc:
|
|
1282
|
+
Migrator.new(:up, migrations, schema_migration, internal_metadata)
|
|
1080
1283
|
end
|
|
1081
1284
|
|
|
1082
|
-
def get_all_versions
|
|
1285
|
+
def get_all_versions # :nodoc:
|
|
1083
1286
|
if schema_migration.table_exists?
|
|
1084
|
-
schema_migration.
|
|
1287
|
+
schema_migration.integer_versions
|
|
1085
1288
|
else
|
|
1086
1289
|
[]
|
|
1087
1290
|
end
|
|
1088
1291
|
end
|
|
1089
1292
|
|
|
1090
|
-
def current_version
|
|
1293
|
+
def current_version # :nodoc:
|
|
1091
1294
|
get_all_versions.max || 0
|
|
1092
1295
|
rescue ActiveRecord::NoDatabaseError
|
|
1093
1296
|
end
|
|
1094
1297
|
|
|
1095
|
-
def needs_migration?
|
|
1096
|
-
|
|
1298
|
+
def needs_migration? # :nodoc:
|
|
1299
|
+
pending_migration_versions.size > 0
|
|
1097
1300
|
end
|
|
1098
1301
|
|
|
1099
|
-
def
|
|
1100
|
-
migrations.
|
|
1302
|
+
def pending_migration_versions # :nodoc:
|
|
1303
|
+
migrations.collect(&:version) - get_all_versions
|
|
1101
1304
|
end
|
|
1102
1305
|
|
|
1103
|
-
def
|
|
1104
|
-
migrations.last || NullMigration.new
|
|
1105
|
-
end
|
|
1106
|
-
|
|
1107
|
-
def migrations
|
|
1306
|
+
def migrations # :nodoc:
|
|
1108
1307
|
migrations = migration_files.map do |file|
|
|
1109
1308
|
version, name, scope = parse_migration_filename(file)
|
|
1110
1309
|
raise IllegalMigrationNameError.new(file) unless version
|
|
1310
|
+
if validate_timestamp? && !valid_migration_timestamp?(version)
|
|
1311
|
+
raise InvalidMigrationTimestampError.new(version, name)
|
|
1312
|
+
end
|
|
1111
1313
|
version = version.to_i
|
|
1112
1314
|
name = name.camelize
|
|
1113
1315
|
|
|
@@ -1117,42 +1319,55 @@ module ActiveRecord
|
|
|
1117
1319
|
migrations.sort_by(&:version)
|
|
1118
1320
|
end
|
|
1119
1321
|
|
|
1120
|
-
def migrations_status
|
|
1322
|
+
def migrations_status # :nodoc:
|
|
1121
1323
|
db_list = schema_migration.normalized_versions
|
|
1122
1324
|
|
|
1123
|
-
file_list = migration_files.
|
|
1325
|
+
file_list = migration_files.filter_map do |file|
|
|
1124
1326
|
version, name, scope = parse_migration_filename(file)
|
|
1125
1327
|
raise IllegalMigrationNameError.new(file) unless version
|
|
1328
|
+
if validate_timestamp? && !valid_migration_timestamp?(version)
|
|
1329
|
+
raise InvalidMigrationTimestampError.new(version, name)
|
|
1330
|
+
end
|
|
1126
1331
|
version = schema_migration.normalize_migration_number(version)
|
|
1127
1332
|
status = db_list.delete(version) ? "up" : "down"
|
|
1128
1333
|
[status, version, (name + scope).humanize]
|
|
1129
|
-
end
|
|
1334
|
+
end
|
|
1130
1335
|
|
|
1131
1336
|
db_list.map! do |version|
|
|
1132
1337
|
["up", version, "********** NO FILE **********"]
|
|
1133
1338
|
end
|
|
1134
1339
|
|
|
1135
|
-
(db_list + file_list).sort_by { |_, version, _| version }
|
|
1340
|
+
(db_list + file_list).sort_by { |_, version, _| version.to_i }
|
|
1136
1341
|
end
|
|
1137
1342
|
|
|
1138
|
-
def current_environment
|
|
1343
|
+
def current_environment # :nodoc:
|
|
1139
1344
|
ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
|
|
1140
1345
|
end
|
|
1141
1346
|
|
|
1142
|
-
def protected_environment?
|
|
1347
|
+
def protected_environment? # :nodoc:
|
|
1143
1348
|
ActiveRecord::Base.protected_environments.include?(last_stored_environment) if last_stored_environment
|
|
1144
1349
|
end
|
|
1145
1350
|
|
|
1146
|
-
def last_stored_environment
|
|
1351
|
+
def last_stored_environment # :nodoc:
|
|
1352
|
+
internal_metadata = connection_pool.internal_metadata
|
|
1353
|
+
return nil unless internal_metadata.enabled?
|
|
1147
1354
|
return nil if current_version == 0
|
|
1148
|
-
raise NoEnvironmentInSchemaError unless
|
|
1355
|
+
raise NoEnvironmentInSchemaError unless internal_metadata.table_exists?
|
|
1149
1356
|
|
|
1150
|
-
environment =
|
|
1357
|
+
environment = internal_metadata[:environment]
|
|
1151
1358
|
raise NoEnvironmentInSchemaError unless environment
|
|
1152
1359
|
environment
|
|
1153
1360
|
end
|
|
1154
1361
|
|
|
1155
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
|
+
|
|
1156
1371
|
def migration_files
|
|
1157
1372
|
paths = Array(migrations_paths)
|
|
1158
1373
|
Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
|
|
@@ -1162,8 +1377,16 @@ module ActiveRecord
|
|
|
1162
1377
|
File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
|
|
1163
1378
|
end
|
|
1164
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
|
+
|
|
1165
1388
|
def move(direction, steps)
|
|
1166
|
-
migrator = Migrator.new(direction, migrations, schema_migration)
|
|
1389
|
+
migrator = Migrator.new(direction, migrations, schema_migration, internal_metadata)
|
|
1167
1390
|
|
|
1168
1391
|
if current_version != 0 && !migrator.current_migration
|
|
1169
1392
|
raise UnknownMigrationVersionError.new(current_version)
|
|
@@ -1178,7 +1401,7 @@ module ActiveRecord
|
|
|
1178
1401
|
|
|
1179
1402
|
finish = migrator.migrations[start_index + steps]
|
|
1180
1403
|
version = finish ? finish.version : 0
|
|
1181
|
-
|
|
1404
|
+
public_send(direction, version)
|
|
1182
1405
|
end
|
|
1183
1406
|
end
|
|
1184
1407
|
|
|
@@ -1188,23 +1411,28 @@ module ActiveRecord
|
|
|
1188
1411
|
|
|
1189
1412
|
# For cases where a table doesn't exist like loading from schema cache
|
|
1190
1413
|
def current_version
|
|
1191
|
-
|
|
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
|
|
1192
1419
|
end
|
|
1193
1420
|
end
|
|
1194
1421
|
|
|
1195
1422
|
self.migrations_paths = ["db/migrate"]
|
|
1196
1423
|
|
|
1197
|
-
def initialize(direction, migrations, schema_migration, target_version = nil)
|
|
1424
|
+
def initialize(direction, migrations, schema_migration, internal_metadata, target_version = nil)
|
|
1198
1425
|
@direction = direction
|
|
1199
1426
|
@target_version = target_version
|
|
1200
1427
|
@migrated_versions = nil
|
|
1201
1428
|
@migrations = migrations
|
|
1202
1429
|
@schema_migration = schema_migration
|
|
1430
|
+
@internal_metadata = internal_metadata
|
|
1203
1431
|
|
|
1204
1432
|
validate(@migrations)
|
|
1205
1433
|
|
|
1206
1434
|
@schema_migration.create_table
|
|
1207
|
-
|
|
1435
|
+
@internal_metadata.create_table
|
|
1208
1436
|
end
|
|
1209
1437
|
|
|
1210
1438
|
def current_version
|
|
@@ -1257,19 +1485,21 @@ module ActiveRecord
|
|
|
1257
1485
|
end
|
|
1258
1486
|
|
|
1259
1487
|
def load_migrated
|
|
1260
|
-
@migrated_versions = Set.new(@schema_migration.
|
|
1488
|
+
@migrated_versions = Set.new(@schema_migration.integer_versions)
|
|
1261
1489
|
end
|
|
1262
1490
|
|
|
1263
1491
|
private
|
|
1492
|
+
def connection
|
|
1493
|
+
ActiveRecord::Tasks::DatabaseTasks.migration_connection
|
|
1494
|
+
end
|
|
1264
1495
|
|
|
1265
1496
|
# Used for running a specific migration.
|
|
1266
1497
|
def run_without_lock
|
|
1267
1498
|
migration = migrations.detect { |m| m.version == @target_version }
|
|
1268
1499
|
raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
|
|
1269
|
-
result = execute_migration_in_transaction(migration, @direction)
|
|
1270
1500
|
|
|
1271
1501
|
record_environment
|
|
1272
|
-
|
|
1502
|
+
execute_migration_in_transaction(migration)
|
|
1273
1503
|
end
|
|
1274
1504
|
|
|
1275
1505
|
# Used for running multiple migrations up to or down to a certain value.
|
|
@@ -1278,18 +1508,15 @@ module ActiveRecord
|
|
|
1278
1508
|
raise UnknownMigrationVersionError.new(@target_version)
|
|
1279
1509
|
end
|
|
1280
1510
|
|
|
1281
|
-
result = runnable.each do |migration|
|
|
1282
|
-
execute_migration_in_transaction(migration, @direction)
|
|
1283
|
-
end
|
|
1284
|
-
|
|
1285
1511
|
record_environment
|
|
1286
|
-
|
|
1512
|
+
runnable.each(&method(:execute_migration_in_transaction))
|
|
1287
1513
|
end
|
|
1288
1514
|
|
|
1289
1515
|
# Stores the current environment in the database.
|
|
1290
1516
|
def record_environment
|
|
1291
1517
|
return if down?
|
|
1292
|
-
|
|
1518
|
+
|
|
1519
|
+
@internal_metadata[:environment] = connection.pool.db_config.env_name
|
|
1293
1520
|
end
|
|
1294
1521
|
|
|
1295
1522
|
def ran?(migration)
|
|
@@ -1301,14 +1528,15 @@ module ActiveRecord
|
|
|
1301
1528
|
@target_version && @target_version != 0 && !target
|
|
1302
1529
|
end
|
|
1303
1530
|
|
|
1304
|
-
def execute_migration_in_transaction(migration
|
|
1531
|
+
def execute_migration_in_transaction(migration)
|
|
1305
1532
|
return if down? && !migrated.include?(migration.version.to_i)
|
|
1306
1533
|
return if up? && migrated.include?(migration.version.to_i)
|
|
1307
1534
|
|
|
1308
|
-
|
|
1535
|
+
message = up? ? "Migrating to" : "Reverting"
|
|
1536
|
+
Base.logger.info "#{message} #{migration.name} (#{migration.version})" if Base.logger
|
|
1309
1537
|
|
|
1310
1538
|
ddl_transaction(migration) do
|
|
1311
|
-
migration.migrate(direction)
|
|
1539
|
+
migration.migrate(@direction)
|
|
1312
1540
|
record_version_state_after_migrating(migration.version)
|
|
1313
1541
|
end
|
|
1314
1542
|
rescue => e
|
|
@@ -1341,10 +1569,10 @@ module ActiveRecord
|
|
|
1341
1569
|
def record_version_state_after_migrating(version)
|
|
1342
1570
|
if down?
|
|
1343
1571
|
migrated.delete(version)
|
|
1344
|
-
@schema_migration.
|
|
1572
|
+
@schema_migration.delete_version(version.to_s)
|
|
1345
1573
|
else
|
|
1346
1574
|
migrated << version
|
|
1347
|
-
@schema_migration.
|
|
1575
|
+
@schema_migration.create_version(version.to_s)
|
|
1348
1576
|
end
|
|
1349
1577
|
end
|
|
1350
1578
|
|
|
@@ -1357,25 +1585,25 @@ module ActiveRecord
|
|
|
1357
1585
|
end
|
|
1358
1586
|
|
|
1359
1587
|
# Wrap the migration in a transaction only if supported by the adapter.
|
|
1360
|
-
def ddl_transaction(migration)
|
|
1588
|
+
def ddl_transaction(migration, &block)
|
|
1361
1589
|
if use_transaction?(migration)
|
|
1362
|
-
|
|
1590
|
+
connection.transaction(&block)
|
|
1363
1591
|
else
|
|
1364
1592
|
yield
|
|
1365
1593
|
end
|
|
1366
1594
|
end
|
|
1367
1595
|
|
|
1368
1596
|
def use_transaction?(migration)
|
|
1369
|
-
!migration.disable_ddl_transaction &&
|
|
1597
|
+
!migration.disable_ddl_transaction && connection.supports_ddl_transactions?
|
|
1370
1598
|
end
|
|
1371
1599
|
|
|
1372
1600
|
def use_advisory_lock?
|
|
1373
|
-
|
|
1601
|
+
connection.advisory_locks_enabled?
|
|
1374
1602
|
end
|
|
1375
1603
|
|
|
1376
1604
|
def with_advisory_lock
|
|
1377
1605
|
lock_id = generate_migrator_advisory_lock_id
|
|
1378
|
-
|
|
1606
|
+
|
|
1379
1607
|
got_lock = connection.get_advisory_lock(lock_id)
|
|
1380
1608
|
raise ConcurrentMigrationError unless got_lock
|
|
1381
1609
|
load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
|
|
@@ -1390,7 +1618,7 @@ module ActiveRecord
|
|
|
1390
1618
|
|
|
1391
1619
|
MIGRATOR_SALT = 2053462845
|
|
1392
1620
|
def generate_migrator_advisory_lock_id
|
|
1393
|
-
db_name_hash = Zlib.crc32(
|
|
1621
|
+
db_name_hash = Zlib.crc32(connection.current_database)
|
|
1394
1622
|
MIGRATOR_SALT * db_name_hash
|
|
1395
1623
|
end
|
|
1396
1624
|
end
|