activerecord 5.2.8.1 → 6.1.6.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1255 -596
- data/MIT-LICENSE +3 -1
- data/README.rdoc +7 -5
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +9 -8
- data/lib/active_record/association_relation.rb +30 -10
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +100 -41
- data/lib/active_record/associations/association_scope.rb +23 -21
- data/lib/active_record/associations/belongs_to_association.rb +55 -48
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -6
- data/lib/active_record/associations/builder/association.rb +45 -22
- data/lib/active_record/associations/builder/belongs_to.rb +29 -59
- data/lib/active_record/associations/builder/collection_association.rb +8 -17
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
- data/lib/active_record/associations/builder/has_many.rb +8 -2
- data/lib/active_record/associations/builder/has_one.rb +33 -2
- data/lib/active_record/associations/builder/singular_association.rb +3 -1
- data/lib/active_record/associations/collection_association.rb +44 -34
- data/lib/active_record/associations/collection_proxy.rb +25 -21
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +26 -13
- data/lib/active_record/associations/has_many_through_association.rb +24 -18
- data/lib/active_record/associations/has_one_association.rb +43 -31
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +44 -22
- data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +91 -60
- data/lib/active_record/associations/preloader/association.rb +69 -43
- data/lib/active_record/associations/preloader/through_association.rb +49 -40
- data/lib/active_record/associations/preloader.rb +47 -34
- data/lib/active_record/associations/singular_association.rb +3 -17
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +137 -25
- data/lib/active_record/attribute_assignment.rb +17 -19
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -7
- data/lib/active_record/attribute_methods/dirty.rb +101 -40
- data/lib/active_record/attribute_methods/primary_key.rb +20 -25
- data/lib/active_record/attribute_methods/query.rb +4 -8
- data/lib/active_record/attribute_methods/read.rb +14 -56
- data/lib/active_record/attribute_methods/serialization.rb +12 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
- data/lib/active_record/attribute_methods/write.rb +18 -34
- data/lib/active_record/attribute_methods.rb +81 -143
- data/lib/active_record/attributes.rb +46 -9
- data/lib/active_record/autosave_association.rb +57 -42
- data/lib/active_record/base.rb +4 -17
- data/lib/active_record/callbacks.rb +158 -43
- data/lib/active_record/coders/yaml_column.rb +1 -2
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +272 -130
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -36
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +167 -146
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -14
- data/lib/active_record/connection_adapters/abstract/quoting.rb +98 -47
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -110
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +211 -90
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -4
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +385 -144
- data/lib/active_record/connection_adapters/abstract/transaction.rb +167 -69
- data/lib/active_record/connection_adapters/abstract_adapter.rb +229 -99
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +243 -275
- data/lib/active_record/connection_adapters/column.rb +30 -12
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +88 -32
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +59 -7
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +18 -7
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +142 -19
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +53 -18
- data/lib/active_record/connection_adapters/pool_config.rb +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +37 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +40 -54
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +47 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +19 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +120 -100
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +224 -120
- data/lib/active_record/connection_adapters/schema_cache.rb +159 -21
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +17 -6
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +77 -13
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +174 -186
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_adapters.rb +52 -0
- data/lib/active_record/connection_handling.rb +293 -33
- data/lib/active_record/core.rb +333 -98
- data/lib/active_record/counter_cache.rb +8 -30
- data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
- data/lib/active_record/database_configurations/database_config.rb +80 -0
- data/lib/active_record/database_configurations/hash_config.rb +96 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/database_configurations.rb +273 -0
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +3 -4
- data/lib/active_record/enum.rb +108 -36
- data/lib/active_record/errors.rb +62 -19
- data/lib/active_record/explain.rb +10 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +10 -17
- data/lib/active_record/fixture_set/model_metadata.rb +32 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +200 -481
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +53 -24
- data/lib/active_record/insert_all.rb +212 -0
- data/lib/active_record/integration.rb +67 -17
- data/lib/active_record/internal_metadata.rb +28 -9
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +37 -23
- data/lib/active_record/locking/pessimistic.rb +9 -5
- data/lib/active_record/log_subscriber.rb +35 -35
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +77 -0
- data/lib/active_record/migration/command_recorder.rb +96 -44
- data/lib/active_record/migration/compatibility.rb +145 -64
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/migration.rb +206 -157
- data/lib/active_record/model_schema.rb +148 -22
- data/lib/active_record/nested_attributes.rb +4 -7
- data/lib/active_record/no_touching.rb +8 -1
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +267 -59
- data/lib/active_record/query_cache.rb +21 -4
- data/lib/active_record/querying.rb +40 -23
- data/lib/active_record/railtie.rb +116 -59
- data/lib/active_record/railties/console_sandbox.rb +2 -4
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +411 -80
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +109 -93
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/batches.rb +44 -35
- data/lib/active_record/relation/calculations.rb +157 -90
- data/lib/active_record/relation/delegation.rb +35 -50
- data/lib/active_record/relation/finder_methods.rb +64 -39
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +32 -40
- data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +11 -10
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +62 -45
- data/lib/active_record/relation/query_attribute.rb +13 -8
- data/lib/active_record/relation/query_methods.rb +476 -187
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +9 -9
- data/lib/active_record/relation/where_clause.rb +115 -62
- data/lib/active_record/relation.rb +379 -115
- data/lib/active_record/result.rb +64 -38
- data/lib/active_record/runtime_registry.rb +2 -2
- data/lib/active_record/sanitization.rb +22 -41
- data/lib/active_record/schema.rb +2 -11
- data/lib/active_record/schema_dumper.rb +54 -9
- data/lib/active_record/schema_migration.rb +7 -9
- data/lib/active_record/scoping/default.rb +4 -8
- data/lib/active_record/scoping/named.rb +17 -24
- data/lib/active_record/scoping.rb +8 -9
- data/lib/active_record/secure_token.rb +16 -8
- data/lib/active_record/serialization.rb +5 -3
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +49 -6
- data/lib/active_record/store.rb +88 -9
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +42 -43
- data/lib/active_record/tasks/database_tasks.rb +277 -81
- data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
- data/lib/active_record/tasks/postgresql_database_tasks.rb +27 -32
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +287 -0
- data/lib/active_record/timestamp.rb +43 -32
- data/lib/active_record/touch_later.rb +23 -22
- data/lib/active_record/transactions.rb +62 -118
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type/adapter_specific_registry.rb +3 -13
- data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
- data/lib/active_record/type/serialized.rb +6 -3
- data/lib/active_record/type/time.rb +10 -0
- data/lib/active_record/type/type_map.rb +0 -1
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type.rb +10 -5
- data/lib/active_record/type_caster/connection.rb +15 -15
- data/lib/active_record/type_caster/map.rb +8 -8
- data/lib/active_record/validations/associated.rb +1 -2
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +38 -30
- data/lib/active_record/validations.rb +4 -3
- data/lib/active_record.rb +13 -12
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +41 -0
- data/lib/arel/collectors/bind.rb +29 -0
- data/lib/arel/collectors/composite.rb +39 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +27 -0
- data/lib/arel/collectors/substitute_binds.rb +35 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +126 -0
- data/lib/arel/nodes/bind_param.rb +44 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +62 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +15 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +76 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +51 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +70 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +250 -0
- data/lib/arel/select_manager.rb +270 -0
- data/lib/arel/table.rb +118 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/dot.rb +308 -0
- data/lib/arel/visitors/mysql.rb +93 -0
- data/lib/arel/visitors/postgresql.rb +120 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +899 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +54 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
- data/lib/rails/generators/active_record/migration.rb +19 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
- 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 +10 -1
- metadata +116 -30
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/collection_cache_key.rb +0 -53
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
- data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -1,11 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "benchmark"
|
3
4
|
require "set"
|
4
5
|
require "zlib"
|
6
|
+
require "active_support/core_ext/array/access"
|
7
|
+
require "active_support/core_ext/enumerable"
|
5
8
|
require "active_support/core_ext/module/attribute_accessors"
|
9
|
+
require "active_support/actionable_error"
|
6
10
|
|
7
11
|
module ActiveRecord
|
8
|
-
class MigrationError < ActiveRecordError#:nodoc:
|
12
|
+
class MigrationError < ActiveRecordError #:nodoc:
|
9
13
|
def initialize(message = nil)
|
10
14
|
message = "\n\n#{message}\n\n" if message
|
11
15
|
super
|
@@ -16,13 +20,13 @@ module ActiveRecord
|
|
16
20
|
# For example the following migration is not reversible.
|
17
21
|
# Rolling back this migration will raise an ActiveRecord::IrreversibleMigration error.
|
18
22
|
#
|
19
|
-
# class IrreversibleMigrationExample < ActiveRecord::Migration[
|
23
|
+
# class IrreversibleMigrationExample < ActiveRecord::Migration[6.0]
|
20
24
|
# def change
|
21
25
|
# create_table :distributors do |t|
|
22
26
|
# t.string :zipcode
|
23
27
|
# end
|
24
28
|
#
|
25
|
-
# execute
|
29
|
+
# execute <<~SQL
|
26
30
|
# ALTER TABLE distributors
|
27
31
|
# ADD CONSTRAINT zipchk
|
28
32
|
# CHECK (char_length(zipcode) = 5) NO INHERIT;
|
@@ -34,13 +38,13 @@ module ActiveRecord
|
|
34
38
|
#
|
35
39
|
# 1. Define <tt>#up</tt> and <tt>#down</tt> methods instead of <tt>#change</tt>:
|
36
40
|
#
|
37
|
-
# class ReversibleMigrationExample < ActiveRecord::Migration[
|
41
|
+
# class ReversibleMigrationExample < ActiveRecord::Migration[6.0]
|
38
42
|
# def up
|
39
43
|
# create_table :distributors do |t|
|
40
44
|
# t.string :zipcode
|
41
45
|
# end
|
42
46
|
#
|
43
|
-
# execute
|
47
|
+
# execute <<~SQL
|
44
48
|
# ALTER TABLE distributors
|
45
49
|
# ADD CONSTRAINT zipchk
|
46
50
|
# CHECK (char_length(zipcode) = 5) NO INHERIT;
|
@@ -48,7 +52,7 @@ module ActiveRecord
|
|
48
52
|
# end
|
49
53
|
#
|
50
54
|
# def down
|
51
|
-
# execute
|
55
|
+
# execute <<~SQL
|
52
56
|
# ALTER TABLE distributors
|
53
57
|
# DROP CONSTRAINT zipchk
|
54
58
|
# SQL
|
@@ -59,7 +63,7 @@ module ActiveRecord
|
|
59
63
|
#
|
60
64
|
# 2. Use the #reversible method in <tt>#change</tt> method:
|
61
65
|
#
|
62
|
-
# class ReversibleMigrationExample < ActiveRecord::Migration[
|
66
|
+
# class ReversibleMigrationExample < ActiveRecord::Migration[6.0]
|
63
67
|
# def change
|
64
68
|
# create_table :distributors do |t|
|
65
69
|
# t.string :zipcode
|
@@ -67,7 +71,7 @@ module ActiveRecord
|
|
67
71
|
#
|
68
72
|
# reversible do |dir|
|
69
73
|
# dir.up do
|
70
|
-
# execute
|
74
|
+
# execute <<~SQL
|
71
75
|
# ALTER TABLE distributors
|
72
76
|
# ADD CONSTRAINT zipchk
|
73
77
|
# CHECK (char_length(zipcode) = 5) NO INHERIT;
|
@@ -75,7 +79,7 @@ module ActiveRecord
|
|
75
79
|
# end
|
76
80
|
#
|
77
81
|
# dir.down do
|
78
|
-
# execute
|
82
|
+
# execute <<~SQL
|
79
83
|
# ALTER TABLE distributors
|
80
84
|
# DROP CONSTRAINT zipchk
|
81
85
|
# SQL
|
@@ -86,7 +90,7 @@ module ActiveRecord
|
|
86
90
|
class IrreversibleMigration < MigrationError
|
87
91
|
end
|
88
92
|
|
89
|
-
class DuplicateMigrationVersionError < MigrationError#:nodoc:
|
93
|
+
class DuplicateMigrationVersionError < MigrationError #:nodoc:
|
90
94
|
def initialize(version = nil)
|
91
95
|
if version
|
92
96
|
super("Multiple migrations have the version number #{version}.")
|
@@ -96,7 +100,7 @@ module ActiveRecord
|
|
96
100
|
end
|
97
101
|
end
|
98
102
|
|
99
|
-
class DuplicateMigrationNameError < MigrationError#:nodoc:
|
103
|
+
class DuplicateMigrationNameError < MigrationError #:nodoc:
|
100
104
|
def initialize(name = nil)
|
101
105
|
if name
|
102
106
|
super("Multiple migrations have the name #{name}.")
|
@@ -116,7 +120,7 @@ module ActiveRecord
|
|
116
120
|
end
|
117
121
|
end
|
118
122
|
|
119
|
-
class IllegalMigrationNameError < MigrationError#:nodoc:
|
123
|
+
class IllegalMigrationNameError < MigrationError #:nodoc:
|
120
124
|
def initialize(name = nil)
|
121
125
|
if name
|
122
126
|
super("Illegal name for migration file: #{name}\n\t(only lower case letters, numbers, and '_' allowed).")
|
@@ -126,21 +130,44 @@ module ActiveRecord
|
|
126
130
|
end
|
127
131
|
end
|
128
132
|
|
129
|
-
class PendingMigrationError < MigrationError#:nodoc:
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
133
|
+
class PendingMigrationError < MigrationError #:nodoc:
|
134
|
+
include ActiveSupport::ActionableError
|
135
|
+
|
136
|
+
action "Run pending migrations" do
|
137
|
+
ActiveRecord::Tasks::DatabaseTasks.migrate
|
138
|
+
|
139
|
+
if ActiveRecord::Base.dump_schema_after_migration
|
140
|
+
ActiveRecord::Tasks::DatabaseTasks.dump_schema(
|
141
|
+
ActiveRecord::Base.connection_db_config
|
142
|
+
)
|
137
143
|
end
|
138
144
|
end
|
145
|
+
|
146
|
+
def initialize(message = nil)
|
147
|
+
super(message || detailed_migration_message)
|
148
|
+
end
|
149
|
+
|
150
|
+
private
|
151
|
+
def detailed_migration_message
|
152
|
+
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)
|
154
|
+
message += "\n\n"
|
155
|
+
|
156
|
+
pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations
|
157
|
+
|
158
|
+
message += "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}\n\n"
|
159
|
+
|
160
|
+
pending_migrations.each do |pending_migration|
|
161
|
+
message += "#{pending_migration.basename}\n"
|
162
|
+
end
|
163
|
+
|
164
|
+
message
|
165
|
+
end
|
139
166
|
end
|
140
167
|
|
141
168
|
class ConcurrentMigrationError < MigrationError #:nodoc:
|
142
|
-
DEFAULT_MESSAGE = "Cannot run migrations because another migration process is currently running."
|
143
|
-
RELEASE_LOCK_FAILED_MESSAGE = "Failed to release advisory lock"
|
169
|
+
DEFAULT_MESSAGE = "Cannot run migrations because another migration process is currently running."
|
170
|
+
RELEASE_LOCK_FAILED_MESSAGE = "Failed to release advisory lock"
|
144
171
|
|
145
172
|
def initialize(message = DEFAULT_MESSAGE)
|
146
173
|
super
|
@@ -160,7 +187,7 @@ module ActiveRecord
|
|
160
187
|
|
161
188
|
class ProtectedEnvironmentError < ActiveRecordError #:nodoc:
|
162
189
|
def initialize(env = "production")
|
163
|
-
msg = "You are attempting to run a destructive action against your '#{env}' database.\n"
|
190
|
+
msg = +"You are attempting to run a destructive action against your '#{env}' database.\n"
|
164
191
|
msg << "If you are sure you want to continue, run the same command with the environment variable:\n"
|
165
192
|
msg << "DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
|
166
193
|
super(msg)
|
@@ -169,7 +196,7 @@ module ActiveRecord
|
|
169
196
|
|
170
197
|
class EnvironmentMismatchError < ActiveRecordError
|
171
198
|
def initialize(current: nil, stored: nil)
|
172
|
-
msg =
|
199
|
+
msg = +"You are attempting to modify a database that was last run in `#{ stored }` environment.\n"
|
173
200
|
msg << "You are running in `#{ current }` environment. "
|
174
201
|
msg << "If you are sure you want to continue, first set the environment using:\n\n"
|
175
202
|
msg << " bin/rails db:environment:set"
|
@@ -181,6 +208,14 @@ module ActiveRecord
|
|
181
208
|
end
|
182
209
|
end
|
183
210
|
|
211
|
+
class EnvironmentStorageError < ActiveRecordError # :nodoc:
|
212
|
+
def initialize
|
213
|
+
msg = +"You are attempting to store the environment in a database where metadata is disabled.\n"
|
214
|
+
msg << "Check your database configuration to see if this is intended."
|
215
|
+
super(msg)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
184
219
|
# = Active Record Migrations
|
185
220
|
#
|
186
221
|
# Migrations can manage the evolution of a schema used by several physical
|
@@ -193,7 +228,7 @@ module ActiveRecord
|
|
193
228
|
#
|
194
229
|
# Example of a simple migration:
|
195
230
|
#
|
196
|
-
# class AddSsl < ActiveRecord::Migration[
|
231
|
+
# class AddSsl < ActiveRecord::Migration[6.0]
|
197
232
|
# def up
|
198
233
|
# add_column :accounts, :ssl_enabled, :boolean, default: true
|
199
234
|
# end
|
@@ -213,7 +248,7 @@ module ActiveRecord
|
|
213
248
|
#
|
214
249
|
# Example of a more complex migration that also needs to initialize data:
|
215
250
|
#
|
216
|
-
# class AddSystemSettings < ActiveRecord::Migration[
|
251
|
+
# class AddSystemSettings < ActiveRecord::Migration[6.0]
|
217
252
|
# def up
|
218
253
|
# create_table :system_settings do |t|
|
219
254
|
# t.string :name
|
@@ -285,7 +320,7 @@ module ActiveRecord
|
|
285
320
|
# +table_name+. Passing a hash containing <tt>:from</tt> and <tt>:to</tt>
|
286
321
|
# as +default_or_changes+ will make this change reversible in the migration.
|
287
322
|
# * <tt>change_column_null(table_name, column_name, null, default = nil)</tt>:
|
288
|
-
# Sets or removes a
|
323
|
+
# Sets or removes a <tt>NOT NULL</tt> constraint on +column_name+. The +null+ flag
|
289
324
|
# indicates whether the value can be +NULL+. See
|
290
325
|
# ActiveRecord::ConnectionAdapters::SchemaStatements#change_column_null for
|
291
326
|
# details.
|
@@ -307,7 +342,7 @@ module ActiveRecord
|
|
307
342
|
# named +column_name+ from the table called +table_name+.
|
308
343
|
# * <tt>remove_columns(table_name, *column_names)</tt>: Removes the given
|
309
344
|
# columns from the table definition.
|
310
|
-
# * <tt>remove_foreign_key(from_table,
|
345
|
+
# * <tt>remove_foreign_key(from_table, to_table = nil, **options)</tt>: Removes the
|
311
346
|
# given foreign key from the table called +table_name+.
|
312
347
|
# * <tt>remove_index(table_name, column: column_names)</tt>: Removes the index
|
313
348
|
# specified by +column_names+.
|
@@ -329,7 +364,7 @@ module ActiveRecord
|
|
329
364
|
# The Rails package has several tools to help create and apply migrations.
|
330
365
|
#
|
331
366
|
# To generate a new migration, you can use
|
332
|
-
# rails generate migration MyNewMigration
|
367
|
+
# bin/rails generate migration MyNewMigration
|
333
368
|
#
|
334
369
|
# where MyNewMigration is the name of your migration. The generator will
|
335
370
|
# create an empty migration file <tt>timestamp_my_new_migration.rb</tt>
|
@@ -338,41 +373,36 @@ module ActiveRecord
|
|
338
373
|
#
|
339
374
|
# There is a special syntactic shortcut to generate migrations that add fields to a table.
|
340
375
|
#
|
341
|
-
# rails generate migration add_fieldname_to_tablename fieldname:string
|
376
|
+
# bin/rails generate migration add_fieldname_to_tablename fieldname:string
|
342
377
|
#
|
343
378
|
# This will generate the file <tt>timestamp_add_fieldname_to_tablename.rb</tt>, which will look like this:
|
344
|
-
# class AddFieldnameToTablename < ActiveRecord::Migration[
|
379
|
+
# class AddFieldnameToTablename < ActiveRecord::Migration[6.0]
|
345
380
|
# def change
|
346
381
|
# add_column :tablenames, :fieldname, :string
|
347
382
|
# end
|
348
383
|
# end
|
349
384
|
#
|
350
385
|
# To run migrations against the currently configured database, use
|
351
|
-
# <tt>rails db:migrate</tt>. This will update the database by running all of the
|
386
|
+
# <tt>bin/rails db:migrate</tt>. This will update the database by running all of the
|
352
387
|
# pending migrations, creating the <tt>schema_migrations</tt> table
|
353
388
|
# (see "About the schema_migrations table" section below) if missing. It will also
|
354
|
-
# invoke the db:schema:dump
|
389
|
+
# invoke the db:schema:dump command, which will update your db/schema.rb file
|
355
390
|
# to match the structure of your database.
|
356
391
|
#
|
357
392
|
# To roll the database back to a previous migration version, use
|
358
|
-
# <tt>rails db:rollback VERSION=X</tt> where <tt>X</tt> is the version to which
|
393
|
+
# <tt>bin/rails db:rollback VERSION=X</tt> where <tt>X</tt> is the version to which
|
359
394
|
# you wish to downgrade. Alternatively, you can also use the STEP option if you
|
360
|
-
# wish to rollback last few migrations. <tt>rails db:rollback STEP=2</tt> will rollback
|
395
|
+
# wish to rollback last few migrations. <tt>bin/rails db:rollback STEP=2</tt> will rollback
|
361
396
|
# the latest two migrations.
|
362
397
|
#
|
363
398
|
# If any of the migrations throw an <tt>ActiveRecord::IrreversibleMigration</tt> exception,
|
364
399
|
# that step will fail and you'll have some manual work to do.
|
365
400
|
#
|
366
|
-
# == Database support
|
367
|
-
#
|
368
|
-
# Migrations are currently supported in MySQL, PostgreSQL, SQLite,
|
369
|
-
# SQL Server, and Oracle (all supported databases except DB2).
|
370
|
-
#
|
371
401
|
# == More examples
|
372
402
|
#
|
373
403
|
# Not all migrations change the schema. Some just fix the data:
|
374
404
|
#
|
375
|
-
# class RemoveEmptyTags < ActiveRecord::Migration[
|
405
|
+
# class RemoveEmptyTags < ActiveRecord::Migration[6.0]
|
376
406
|
# def up
|
377
407
|
# Tag.all.each { |tag| tag.destroy if tag.pages.empty? }
|
378
408
|
# end
|
@@ -385,7 +415,7 @@ module ActiveRecord
|
|
385
415
|
#
|
386
416
|
# Others remove columns when they migrate up instead of down:
|
387
417
|
#
|
388
|
-
# class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[
|
418
|
+
# class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[6.0]
|
389
419
|
# def up
|
390
420
|
# remove_column :items, :incomplete_items_count
|
391
421
|
# remove_column :items, :completed_items_count
|
@@ -399,7 +429,7 @@ module ActiveRecord
|
|
399
429
|
#
|
400
430
|
# And sometimes you need to do something in SQL not abstracted directly by migrations:
|
401
431
|
#
|
402
|
-
# class MakeJoinUnique < ActiveRecord::Migration[
|
432
|
+
# class MakeJoinUnique < ActiveRecord::Migration[6.0]
|
403
433
|
# def up
|
404
434
|
# execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)"
|
405
435
|
# end
|
@@ -416,7 +446,7 @@ module ActiveRecord
|
|
416
446
|
# <tt>Base#reset_column_information</tt> in order to ensure that the model has the
|
417
447
|
# latest column data from after the new column was added. Example:
|
418
448
|
#
|
419
|
-
# class AddPeopleSalary < ActiveRecord::Migration[
|
449
|
+
# class AddPeopleSalary < ActiveRecord::Migration[6.0]
|
420
450
|
# def up
|
421
451
|
# add_column :people, :salary, :integer
|
422
452
|
# Person.reset_column_information
|
@@ -474,7 +504,7 @@ module ActiveRecord
|
|
474
504
|
# To define a reversible migration, define the +change+ method in your
|
475
505
|
# migration like this:
|
476
506
|
#
|
477
|
-
# class TenderloveMigration < ActiveRecord::Migration[
|
507
|
+
# class TenderloveMigration < ActiveRecord::Migration[6.0]
|
478
508
|
# def change
|
479
509
|
# create_table(:horses) do |t|
|
480
510
|
# t.column :content, :text
|
@@ -486,9 +516,9 @@ module ActiveRecord
|
|
486
516
|
# This migration will create the horses table for you on the way up, and
|
487
517
|
# automatically figure out how to drop the table on the way down.
|
488
518
|
#
|
489
|
-
# Some commands
|
490
|
-
#
|
491
|
-
#
|
519
|
+
# Some commands cannot be reversed. If you care to define how to move up
|
520
|
+
# and down in these cases, you should define the +up+ and +down+ methods
|
521
|
+
# as before.
|
492
522
|
#
|
493
523
|
# If a command cannot be reversed, an
|
494
524
|
# <tt>ActiveRecord::IrreversibleMigration</tt> exception will be raised when
|
@@ -504,7 +534,7 @@ module ActiveRecord
|
|
504
534
|
# can't execute inside a transaction though, and for these situations
|
505
535
|
# you can turn the automatic transactions off.
|
506
536
|
#
|
507
|
-
# class ChangeEnum < ActiveRecord::Migration[
|
537
|
+
# class ChangeEnum < ActiveRecord::Migration[6.0]
|
508
538
|
# disable_ddl_transaction!
|
509
539
|
#
|
510
540
|
# def up
|
@@ -517,12 +547,13 @@ module ActiveRecord
|
|
517
547
|
class Migration
|
518
548
|
autoload :CommandRecorder, "active_record/migration/command_recorder"
|
519
549
|
autoload :Compatibility, "active_record/migration/compatibility"
|
550
|
+
autoload :JoinTable, "active_record/migration/join_table"
|
520
551
|
|
521
552
|
# This must be defined before the inherited hook, below
|
522
|
-
class Current < Migration
|
553
|
+
class Current < Migration #:nodoc:
|
523
554
|
end
|
524
555
|
|
525
|
-
def self.inherited(subclass)
|
556
|
+
def self.inherited(subclass) #:nodoc:
|
526
557
|
super
|
527
558
|
if subclass.superclass == Migration
|
528
559
|
raise StandardError, "Directly inheriting from ActiveRecord::Migration is not supported. " \
|
@@ -540,26 +571,41 @@ module ActiveRecord
|
|
540
571
|
ActiveRecord::VERSION::STRING.to_f
|
541
572
|
end
|
542
573
|
|
543
|
-
MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/
|
574
|
+
MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/ #:nodoc:
|
544
575
|
|
545
576
|
# This class is used to verify that all migrations have been run before
|
546
577
|
# loading a web page if <tt>config.active_record.migration_error</tt> is set to :page_load
|
547
578
|
class CheckPending
|
548
|
-
def initialize(app)
|
579
|
+
def initialize(app, file_watcher: ActiveSupport::FileUpdateChecker)
|
549
580
|
@app = app
|
550
|
-
@
|
581
|
+
@needs_check = true
|
582
|
+
@mutex = Mutex.new
|
583
|
+
@file_watcher = file_watcher
|
551
584
|
end
|
552
585
|
|
553
586
|
def call(env)
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
587
|
+
@mutex.synchronize do
|
588
|
+
@watcher ||= build_watcher do
|
589
|
+
@needs_check = true
|
590
|
+
ActiveRecord::Migration.check_pending!(connection)
|
591
|
+
@needs_check = false
|
592
|
+
end
|
593
|
+
|
594
|
+
if @needs_check
|
595
|
+
@watcher.execute
|
596
|
+
else
|
597
|
+
@watcher.execute_if_updated
|
598
|
+
end
|
558
599
|
end
|
600
|
+
|
559
601
|
@app.call(env)
|
560
602
|
end
|
561
603
|
|
562
604
|
private
|
605
|
+
def build_watcher(&block)
|
606
|
+
paths = Array(connection.migration_context.migrations_paths)
|
607
|
+
@file_watcher.new([], paths.index_with(["rb"]), &block)
|
608
|
+
end
|
563
609
|
|
564
610
|
def connection
|
565
611
|
ActiveRecord::Base.connection
|
@@ -567,10 +613,10 @@ module ActiveRecord
|
|
567
613
|
end
|
568
614
|
|
569
615
|
class << self
|
570
|
-
attr_accessor :delegate
|
571
|
-
attr_accessor :disable_ddl_transaction
|
616
|
+
attr_accessor :delegate #:nodoc:
|
617
|
+
attr_accessor :disable_ddl_transaction #:nodoc:
|
572
618
|
|
573
|
-
def nearest_delegate
|
619
|
+
def nearest_delegate #:nodoc:
|
574
620
|
delegate || superclass.nearest_delegate
|
575
621
|
end
|
576
622
|
|
@@ -580,29 +626,38 @@ module ActiveRecord
|
|
580
626
|
end
|
581
627
|
|
582
628
|
def load_schema_if_pending!
|
583
|
-
|
629
|
+
current_db_config = Base.connection_db_config
|
630
|
+
all_configs = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env)
|
631
|
+
|
632
|
+
needs_update = !all_configs.all? do |db_config|
|
633
|
+
Tasks::DatabaseTasks.schema_up_to_date?(db_config, ActiveRecord::Base.schema_format)
|
634
|
+
end
|
635
|
+
|
636
|
+
if needs_update
|
584
637
|
# Roundtrip to Rake to allow plugins to hook into database initialization.
|
585
638
|
root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
|
586
639
|
FileUtils.cd(root) do
|
587
|
-
current_config = Base.connection_config
|
588
640
|
Base.clear_all_connections!
|
589
641
|
system("bin/rails db:test:prepare")
|
590
|
-
# Establish a new connection, the old database may be gone (db:test:prepare uses purge)
|
591
|
-
Base.establish_connection(current_config)
|
592
642
|
end
|
593
|
-
check_pending!
|
594
643
|
end
|
644
|
+
|
645
|
+
# Establish a new connection, the old database may be gone (db:test:prepare uses purge)
|
646
|
+
Base.establish_connection(current_db_config)
|
647
|
+
|
648
|
+
check_pending!
|
595
649
|
end
|
596
650
|
|
597
|
-
def maintain_test_schema!
|
651
|
+
def maintain_test_schema! #:nodoc:
|
598
652
|
if ActiveRecord::Base.maintain_test_schema
|
599
653
|
suppress_messages { load_schema_if_pending! }
|
600
654
|
end
|
601
655
|
end
|
602
656
|
|
603
|
-
def method_missing(name, *args, &block)
|
657
|
+
def method_missing(name, *args, &block) #:nodoc:
|
604
658
|
nearest_delegate.send(name, *args, &block)
|
605
659
|
end
|
660
|
+
ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
|
606
661
|
|
607
662
|
def migrate(direction)
|
608
663
|
new.migrate direction
|
@@ -617,7 +672,7 @@ module ActiveRecord
|
|
617
672
|
end
|
618
673
|
end
|
619
674
|
|
620
|
-
def disable_ddl_transaction
|
675
|
+
def disable_ddl_transaction #:nodoc:
|
621
676
|
self.class.disable_ddl_transaction
|
622
677
|
end
|
623
678
|
|
@@ -641,7 +696,7 @@ module ActiveRecord
|
|
641
696
|
# and create the table 'apples' on the way up, and the reverse
|
642
697
|
# on the way down.
|
643
698
|
#
|
644
|
-
# class FixTLMigration < ActiveRecord::Migration[
|
699
|
+
# class FixTLMigration < ActiveRecord::Migration[6.0]
|
645
700
|
# def change
|
646
701
|
# revert do
|
647
702
|
# create_table(:horses) do |t|
|
@@ -658,9 +713,9 @@ module ActiveRecord
|
|
658
713
|
# Or equivalently, if +TenderloveMigration+ is defined as in the
|
659
714
|
# documentation for Migration:
|
660
715
|
#
|
661
|
-
# require_relative
|
716
|
+
# require_relative "20121212123456_tenderlove_migration"
|
662
717
|
#
|
663
|
-
# class FixupTLMigration < ActiveRecord::Migration[
|
718
|
+
# class FixupTLMigration < ActiveRecord::Migration[6.0]
|
664
719
|
# def change
|
665
720
|
# revert TenderloveMigration
|
666
721
|
#
|
@@ -677,15 +732,13 @@ module ActiveRecord
|
|
677
732
|
if connection.respond_to? :revert
|
678
733
|
connection.revert { yield }
|
679
734
|
else
|
680
|
-
recorder =
|
735
|
+
recorder = command_recorder
|
681
736
|
@connection = recorder
|
682
737
|
suppress_messages do
|
683
738
|
connection.revert { yield }
|
684
739
|
end
|
685
740
|
@connection = recorder.delegate
|
686
|
-
recorder.
|
687
|
-
send(cmd, *args, &block)
|
688
|
-
end
|
741
|
+
recorder.replay(self)
|
689
742
|
end
|
690
743
|
end
|
691
744
|
end
|
@@ -694,7 +747,7 @@ module ActiveRecord
|
|
694
747
|
connection.respond_to?(:reverting) && connection.reverting
|
695
748
|
end
|
696
749
|
|
697
|
-
ReversibleBlockHelper = Struct.new(:reverting) do
|
750
|
+
ReversibleBlockHelper = Struct.new(:reverting) do #:nodoc:
|
698
751
|
def up
|
699
752
|
yield unless reverting
|
700
753
|
end
|
@@ -713,7 +766,7 @@ module ActiveRecord
|
|
713
766
|
# when the three columns 'first_name', 'last_name' and 'full_name' exist,
|
714
767
|
# even when migrating down:
|
715
768
|
#
|
716
|
-
# class SplitNameMigration < ActiveRecord::Migration[
|
769
|
+
# class SplitNameMigration < ActiveRecord::Migration[6.0]
|
717
770
|
# def change
|
718
771
|
# add_column :users, :first_name, :string
|
719
772
|
# add_column :users, :last_name, :string
|
@@ -741,7 +794,7 @@ module ActiveRecord
|
|
741
794
|
# In the following example, the new column +published+ will be given
|
742
795
|
# the value +true+ for all existing records.
|
743
796
|
#
|
744
|
-
# class AddPublishedToPosts < ActiveRecord::Migration[
|
797
|
+
# class AddPublishedToPosts < ActiveRecord::Migration[6.0]
|
745
798
|
# def change
|
746
799
|
# add_column :posts, :published, :boolean, default: false
|
747
800
|
# up_only do
|
@@ -814,7 +867,7 @@ module ActiveRecord
|
|
814
867
|
change
|
815
868
|
end
|
816
869
|
else
|
817
|
-
|
870
|
+
public_send(direction)
|
818
871
|
end
|
819
872
|
ensure
|
820
873
|
@connection = nil
|
@@ -830,10 +883,14 @@ module ActiveRecord
|
|
830
883
|
write "== %s %s" % [text, "=" * length]
|
831
884
|
end
|
832
885
|
|
886
|
+
# Takes a message argument and outputs it as is.
|
887
|
+
# A second boolean argument can be passed to specify whether to indent or not.
|
833
888
|
def say(message, subitem = false)
|
834
889
|
write "#{subitem ? " ->" : "--"} #{message}"
|
835
890
|
end
|
836
891
|
|
892
|
+
# Outputs text along with how long it took to run its block.
|
893
|
+
# If the block returns an integer it assumes it is the number of rows affected.
|
837
894
|
def say_with_time(message)
|
838
895
|
say(message)
|
839
896
|
result = nil
|
@@ -843,6 +900,7 @@ module ActiveRecord
|
|
843
900
|
result
|
844
901
|
end
|
845
902
|
|
903
|
+
# Takes a block as an argument and suppresses any output generated by the block.
|
846
904
|
def suppress_messages
|
847
905
|
save, self.verbose = verbose, false
|
848
906
|
yield
|
@@ -871,21 +929,23 @@ module ActiveRecord
|
|
871
929
|
connection.send(method, *arguments, &block)
|
872
930
|
end
|
873
931
|
end
|
932
|
+
ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
|
874
933
|
|
875
934
|
def copy(destination, sources, options = {})
|
876
935
|
copied = []
|
936
|
+
schema_migration = options[:schema_migration] || ActiveRecord::SchemaMigration
|
877
937
|
|
878
938
|
FileUtils.mkdir_p(destination) unless File.exist?(destination)
|
879
939
|
|
880
|
-
destination_migrations = ActiveRecord::MigrationContext.new(destination).migrations
|
940
|
+
destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration).migrations
|
881
941
|
last = destination_migrations.last
|
882
942
|
sources.each do |scope, path|
|
883
|
-
source_migrations = ActiveRecord::MigrationContext.new(path).migrations
|
943
|
+
source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration).migrations
|
884
944
|
|
885
945
|
source_migrations.each do |migration|
|
886
946
|
source = File.binread(migration.filename)
|
887
947
|
inserted_comment = "# This migration comes from #{scope} (originally #{migration.version})\n"
|
888
|
-
magic_comments = ""
|
948
|
+
magic_comments = +""
|
889
949
|
loop do
|
890
950
|
# If we have a magic comment in the original migration,
|
891
951
|
# insert our comment after the first newline(end of the magic comment line)
|
@@ -956,6 +1016,10 @@ module ActiveRecord
|
|
956
1016
|
yield
|
957
1017
|
end
|
958
1018
|
end
|
1019
|
+
|
1020
|
+
def command_recorder
|
1021
|
+
CommandRecorder.new(connection)
|
1022
|
+
end
|
959
1023
|
end
|
960
1024
|
|
961
1025
|
# MigrationProxy is used to defer loading of the actual migration classes
|
@@ -970,14 +1034,9 @@ module ActiveRecord
|
|
970
1034
|
File.basename(filename)
|
971
1035
|
end
|
972
1036
|
|
973
|
-
def mtime
|
974
|
-
File.mtime filename
|
975
|
-
end
|
976
|
-
|
977
1037
|
delegate :migrate, :announce, :write, :disable_ddl_transaction, to: :migration
|
978
1038
|
|
979
1039
|
private
|
980
|
-
|
981
1040
|
def migration
|
982
1041
|
@migration ||= load_migration
|
983
1042
|
end
|
@@ -988,21 +1047,12 @@ module ActiveRecord
|
|
988
1047
|
end
|
989
1048
|
end
|
990
1049
|
|
991
|
-
class
|
992
|
-
|
993
|
-
super(nil, 0, nil, nil)
|
994
|
-
end
|
1050
|
+
class MigrationContext #:nodoc:
|
1051
|
+
attr_reader :migrations_paths, :schema_migration
|
995
1052
|
|
996
|
-
def
|
997
|
-
0
|
998
|
-
end
|
999
|
-
end
|
1000
|
-
|
1001
|
-
class MigrationContext # :nodoc:
|
1002
|
-
attr_reader :migrations_paths
|
1003
|
-
|
1004
|
-
def initialize(migrations_paths)
|
1053
|
+
def initialize(migrations_paths, schema_migration)
|
1005
1054
|
@migrations_paths = migrations_paths
|
1055
|
+
@schema_migration = schema_migration
|
1006
1056
|
end
|
1007
1057
|
|
1008
1058
|
def migrate(target_version = nil, &block)
|
@@ -1033,7 +1083,7 @@ module ActiveRecord
|
|
1033
1083
|
migrations
|
1034
1084
|
end
|
1035
1085
|
|
1036
|
-
Migrator.new(:up, selected_migrations, target_version).migrate
|
1086
|
+
Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate
|
1037
1087
|
end
|
1038
1088
|
|
1039
1089
|
def down(target_version = nil)
|
@@ -1043,20 +1093,20 @@ module ActiveRecord
|
|
1043
1093
|
migrations
|
1044
1094
|
end
|
1045
1095
|
|
1046
|
-
Migrator.new(:down, selected_migrations, target_version).migrate
|
1096
|
+
Migrator.new(:down, selected_migrations, schema_migration, target_version).migrate
|
1047
1097
|
end
|
1048
1098
|
|
1049
1099
|
def run(direction, target_version)
|
1050
|
-
Migrator.new(direction, migrations, target_version).run
|
1100
|
+
Migrator.new(direction, migrations, schema_migration, target_version).run
|
1051
1101
|
end
|
1052
1102
|
|
1053
1103
|
def open
|
1054
|
-
Migrator.new(:up, migrations,
|
1104
|
+
Migrator.new(:up, migrations, schema_migration)
|
1055
1105
|
end
|
1056
1106
|
|
1057
1107
|
def get_all_versions
|
1058
|
-
if
|
1059
|
-
|
1108
|
+
if schema_migration.table_exists?
|
1109
|
+
schema_migration.all_versions.map(&:to_i)
|
1060
1110
|
else
|
1061
1111
|
[]
|
1062
1112
|
end
|
@@ -1075,14 +1125,6 @@ module ActiveRecord
|
|
1075
1125
|
migrations.any?
|
1076
1126
|
end
|
1077
1127
|
|
1078
|
-
def last_migration #:nodoc:
|
1079
|
-
migrations.last || NullMigration.new
|
1080
|
-
end
|
1081
|
-
|
1082
|
-
def parse_migration_filename(filename) # :nodoc:
|
1083
|
-
File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
|
1084
|
-
end
|
1085
|
-
|
1086
1128
|
def migrations
|
1087
1129
|
migrations = migration_files.map do |file|
|
1088
1130
|
version, name, scope = parse_migration_filename(file)
|
@@ -1097,12 +1139,12 @@ module ActiveRecord
|
|
1097
1139
|
end
|
1098
1140
|
|
1099
1141
|
def migrations_status
|
1100
|
-
db_list =
|
1142
|
+
db_list = schema_migration.normalized_versions
|
1101
1143
|
|
1102
1144
|
file_list = migration_files.map do |file|
|
1103
1145
|
version, name, scope = parse_migration_filename(file)
|
1104
1146
|
raise IllegalMigrationNameError.new(file) unless version
|
1105
|
-
version =
|
1147
|
+
version = schema_migration.normalize_migration_number(version)
|
1106
1148
|
status = db_list.delete(version) ? "up" : "down"
|
1107
1149
|
[status, version, (name + scope).humanize]
|
1108
1150
|
end.compact
|
@@ -1114,11 +1156,6 @@ module ActiveRecord
|
|
1114
1156
|
(db_list + file_list).sort_by { |_, version, _| version }
|
1115
1157
|
end
|
1116
1158
|
|
1117
|
-
def migration_files
|
1118
|
-
paths = Array(migrations_paths)
|
1119
|
-
Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
|
1120
|
-
end
|
1121
|
-
|
1122
1159
|
def current_environment
|
1123
1160
|
ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
|
1124
1161
|
end
|
@@ -1128,6 +1165,7 @@ module ActiveRecord
|
|
1128
1165
|
end
|
1129
1166
|
|
1130
1167
|
def last_stored_environment
|
1168
|
+
return nil unless ActiveRecord::InternalMetadata.enabled?
|
1131
1169
|
return nil if current_version == 0
|
1132
1170
|
raise NoEnvironmentInSchemaError unless ActiveRecord::InternalMetadata.table_exists?
|
1133
1171
|
|
@@ -1137,8 +1175,17 @@ module ActiveRecord
|
|
1137
1175
|
end
|
1138
1176
|
|
1139
1177
|
private
|
1178
|
+
def migration_files
|
1179
|
+
paths = Array(migrations_paths)
|
1180
|
+
Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
|
1181
|
+
end
|
1182
|
+
|
1183
|
+
def parse_migration_filename(filename)
|
1184
|
+
File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
|
1185
|
+
end
|
1186
|
+
|
1140
1187
|
def move(direction, steps)
|
1141
|
-
migrator = Migrator.new(direction, migrations)
|
1188
|
+
migrator = Migrator.new(direction, migrations, schema_migration)
|
1142
1189
|
|
1143
1190
|
if current_version != 0 && !migrator.current_migration
|
1144
1191
|
raise UnknownMigrationVersionError.new(current_version)
|
@@ -1153,7 +1200,7 @@ module ActiveRecord
|
|
1153
1200
|
|
1154
1201
|
finish = migrator.migrations[start_index + steps]
|
1155
1202
|
version = finish ? finish.version : 0
|
1156
|
-
|
1203
|
+
public_send(direction, version)
|
1157
1204
|
end
|
1158
1205
|
end
|
1159
1206
|
|
@@ -1161,30 +1208,24 @@ module ActiveRecord
|
|
1161
1208
|
class << self
|
1162
1209
|
attr_accessor :migrations_paths
|
1163
1210
|
|
1164
|
-
def migrations_path=(path)
|
1165
|
-
ActiveSupport::Deprecation.warn \
|
1166
|
-
"`ActiveRecord::Migrator.migrations_path=` is now deprecated and will be removed in Rails 6.0. " \
|
1167
|
-
"You can set the `migrations_paths` on the `connection` instead through the `database.yml`."
|
1168
|
-
self.migrations_paths = [path]
|
1169
|
-
end
|
1170
|
-
|
1171
1211
|
# For cases where a table doesn't exist like loading from schema cache
|
1172
1212
|
def current_version
|
1173
|
-
MigrationContext.new(migrations_paths).current_version
|
1213
|
+
MigrationContext.new(migrations_paths, SchemaMigration).current_version
|
1174
1214
|
end
|
1175
1215
|
end
|
1176
1216
|
|
1177
1217
|
self.migrations_paths = ["db/migrate"]
|
1178
1218
|
|
1179
|
-
def initialize(direction, migrations, target_version = nil)
|
1219
|
+
def initialize(direction, migrations, schema_migration, target_version = nil)
|
1180
1220
|
@direction = direction
|
1181
1221
|
@target_version = target_version
|
1182
1222
|
@migrated_versions = nil
|
1183
1223
|
@migrations = migrations
|
1224
|
+
@schema_migration = schema_migration
|
1184
1225
|
|
1185
1226
|
validate(@migrations)
|
1186
1227
|
|
1187
|
-
|
1228
|
+
@schema_migration.create_table
|
1188
1229
|
ActiveRecord::InternalMetadata.create_table
|
1189
1230
|
end
|
1190
1231
|
|
@@ -1238,16 +1279,15 @@ module ActiveRecord
|
|
1238
1279
|
end
|
1239
1280
|
|
1240
1281
|
def load_migrated
|
1241
|
-
@migrated_versions = Set.new(
|
1282
|
+
@migrated_versions = Set.new(@schema_migration.all_versions.map(&:to_i))
|
1242
1283
|
end
|
1243
1284
|
|
1244
1285
|
private
|
1245
|
-
|
1246
1286
|
# Used for running a specific migration.
|
1247
1287
|
def run_without_lock
|
1248
1288
|
migration = migrations.detect { |m| m.version == @target_version }
|
1249
1289
|
raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
|
1250
|
-
result = execute_migration_in_transaction(migration
|
1290
|
+
result = execute_migration_in_transaction(migration)
|
1251
1291
|
|
1252
1292
|
record_environment
|
1253
1293
|
result
|
@@ -1259,10 +1299,7 @@ module ActiveRecord
|
|
1259
1299
|
raise UnknownMigrationVersionError.new(@target_version)
|
1260
1300
|
end
|
1261
1301
|
|
1262
|
-
result = runnable.each
|
1263
|
-
execute_migration_in_transaction(migration, @direction)
|
1264
|
-
end
|
1265
|
-
|
1302
|
+
result = runnable.each(&method(:execute_migration_in_transaction))
|
1266
1303
|
record_environment
|
1267
1304
|
result
|
1268
1305
|
end
|
@@ -1282,18 +1319,18 @@ module ActiveRecord
|
|
1282
1319
|
@target_version && @target_version != 0 && !target
|
1283
1320
|
end
|
1284
1321
|
|
1285
|
-
def execute_migration_in_transaction(migration
|
1322
|
+
def execute_migration_in_transaction(migration)
|
1286
1323
|
return if down? && !migrated.include?(migration.version.to_i)
|
1287
1324
|
return if up? && migrated.include?(migration.version.to_i)
|
1288
1325
|
|
1289
1326
|
Base.logger.info "Migrating to #{migration.name} (#{migration.version})" if Base.logger
|
1290
1327
|
|
1291
1328
|
ddl_transaction(migration) do
|
1292
|
-
migration.migrate(direction)
|
1329
|
+
migration.migrate(@direction)
|
1293
1330
|
record_version_state_after_migrating(migration.version)
|
1294
1331
|
end
|
1295
1332
|
rescue => e
|
1296
|
-
msg = "An error has occurred, "
|
1333
|
+
msg = +"An error has occurred, "
|
1297
1334
|
msg << "this and " if use_transaction?(migration)
|
1298
1335
|
msg << "all later migrations canceled:\n\n#{e}"
|
1299
1336
|
raise StandardError, msg, e.backtrace
|
@@ -1322,10 +1359,10 @@ module ActiveRecord
|
|
1322
1359
|
def record_version_state_after_migrating(version)
|
1323
1360
|
if down?
|
1324
1361
|
migrated.delete(version)
|
1325
|
-
|
1362
|
+
@schema_migration.delete_by(version: version.to_s)
|
1326
1363
|
else
|
1327
1364
|
migrated << version
|
1328
|
-
|
1365
|
+
@schema_migration.create!(version: version.to_s)
|
1329
1366
|
end
|
1330
1367
|
end
|
1331
1368
|
|
@@ -1351,24 +1388,36 @@ module ActiveRecord
|
|
1351
1388
|
end
|
1352
1389
|
|
1353
1390
|
def use_advisory_lock?
|
1354
|
-
Base.connection.
|
1391
|
+
Base.connection.advisory_locks_enabled?
|
1355
1392
|
end
|
1356
1393
|
|
1357
1394
|
def with_advisory_lock
|
1358
1395
|
lock_id = generate_migrator_advisory_lock_id
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1366
|
-
|
1367
|
-
ConcurrentMigrationError
|
1368
|
-
|
1396
|
+
|
1397
|
+
with_advisory_lock_connection do |connection|
|
1398
|
+
got_lock = connection.get_advisory_lock(lock_id)
|
1399
|
+
raise ConcurrentMigrationError unless got_lock
|
1400
|
+
load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
|
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
|
1369
1408
|
end
|
1370
1409
|
end
|
1371
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) }
|
1417
|
+
ensure
|
1418
|
+
pool&.disconnect!
|
1419
|
+
end
|
1420
|
+
|
1372
1421
|
MIGRATOR_SALT = 2053462845
|
1373
1422
|
def generate_migrator_advisory_lock_id
|
1374
1423
|
db_name_hash = Zlib.crc32(Base.connection.current_database)
|