activerecord 5.2.4.3 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
 - data/CHANGELOG.md +614 -588
 - data/MIT-LICENSE +3 -1
 - data/README.rdoc +4 -2
 - data/examples/performance.rb +1 -1
 - data/lib/active_record.rb +9 -2
 - data/lib/active_record/aggregations.rb +4 -2
 - data/lib/active_record/associations.rb +19 -14
 - data/lib/active_record/associations/association.rb +52 -19
 - data/lib/active_record/associations/association_scope.rb +4 -6
 - data/lib/active_record/associations/belongs_to_association.rb +36 -42
 - data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
 - data/lib/active_record/associations/builder/association.rb +14 -18
 - data/lib/active_record/associations/builder/belongs_to.rb +19 -52
 - data/lib/active_record/associations/builder/collection_association.rb +3 -13
 - data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -38
 - data/lib/active_record/associations/builder/has_many.rb +2 -0
 - data/lib/active_record/associations/builder/has_one.rb +35 -1
 - data/lib/active_record/associations/builder/singular_association.rb +2 -0
 - data/lib/active_record/associations/collection_association.rb +6 -21
 - data/lib/active_record/associations/collection_proxy.rb +12 -15
 - data/lib/active_record/associations/foreign_association.rb +7 -0
 - data/lib/active_record/associations/has_many_association.rb +2 -10
 - data/lib/active_record/associations/has_many_through_association.rb +14 -14
 - data/lib/active_record/associations/has_one_association.rb +28 -30
 - data/lib/active_record/associations/has_one_through_association.rb +5 -5
 - data/lib/active_record/associations/join_dependency.rb +24 -28
 - data/lib/active_record/associations/join_dependency/join_association.rb +9 -10
 - data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
 - data/lib/active_record/associations/preloader.rb +40 -32
 - data/lib/active_record/associations/preloader/association.rb +38 -36
 - data/lib/active_record/associations/preloader/through_association.rb +48 -39
 - data/lib/active_record/associations/singular_association.rb +2 -16
 - data/lib/active_record/attribute_assignment.rb +7 -10
 - data/lib/active_record/attribute_methods.rb +28 -100
 - data/lib/active_record/attribute_methods/before_type_cast.rb +4 -1
 - data/lib/active_record/attribute_methods/dirty.rb +111 -40
 - data/lib/active_record/attribute_methods/primary_key.rb +15 -22
 - data/lib/active_record/attribute_methods/query.rb +2 -3
 - data/lib/active_record/attribute_methods/read.rb +15 -53
 - data/lib/active_record/attribute_methods/serialization.rb +1 -1
 - data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
 - data/lib/active_record/attribute_methods/write.rb +17 -24
 - data/lib/active_record/attributes.rb +13 -0
 - data/lib/active_record/autosave_association.rb +5 -9
 - data/lib/active_record/base.rb +2 -3
 - data/lib/active_record/callbacks.rb +5 -19
 - data/lib/active_record/connection_adapters/abstract/connection_pool.rb +94 -16
 - data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -4
 - data/lib/active_record/connection_adapters/abstract/database_statements.rb +95 -123
 - data/lib/active_record/connection_adapters/abstract/query_cache.rb +17 -8
 - data/lib/active_record/connection_adapters/abstract/quoting.rb +68 -17
 - data/lib/active_record/connection_adapters/abstract/schema_creation.rb +19 -12
 - data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +76 -48
 - data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -3
 - data/lib/active_record/connection_adapters/abstract/schema_statements.rb +132 -53
 - data/lib/active_record/connection_adapters/abstract/transaction.rb +96 -56
 - data/lib/active_record/connection_adapters/abstract_adapter.rb +180 -47
 - data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +128 -194
 - data/lib/active_record/connection_adapters/column.rb +17 -13
 - data/lib/active_record/connection_adapters/connection_specification.rb +52 -42
 - data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +6 -10
 - data/lib/active_record/connection_adapters/mysql/database_statements.rb +73 -13
 - data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
 - data/lib/active_record/connection_adapters/mysql/schema_creation.rb +3 -4
 - data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +40 -32
 - data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +14 -6
 - data/lib/active_record/connection_adapters/mysql/schema_statements.rb +129 -13
 - data/lib/active_record/connection_adapters/mysql/type_metadata.rb +6 -10
 - data/lib/active_record/connection_adapters/mysql2_adapter.rb +26 -9
 - data/lib/active_record/connection_adapters/postgresql/column.rb +17 -31
 - data/lib/active_record/connection_adapters/postgresql/database_statements.rb +20 -1
 - data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
 - data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
 - data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -1
 - data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -1
 - data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
 - data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -1
 - data/lib/active_record/connection_adapters/postgresql/oid/range.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 +6 -3
 - data/lib/active_record/connection_adapters/postgresql/quoting.rb +44 -7
 - data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +12 -1
 - data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
 - data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +55 -53
 - data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +24 -27
 - data/lib/active_record/connection_adapters/postgresql_adapter.rb +160 -74
 - data/lib/active_record/connection_adapters/schema_cache.rb +37 -14
 - data/lib/active_record/connection_adapters/sql_type_metadata.rb +11 -8
 - data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
 - data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -6
 - data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +42 -11
 - data/lib/active_record/connection_adapters/sqlite3_adapter.rb +125 -141
 - data/lib/active_record/connection_handling.rb +149 -27
 - data/lib/active_record/core.rb +100 -60
 - data/lib/active_record/counter_cache.rb +4 -29
 - data/lib/active_record/database_configurations.rb +233 -0
 - data/lib/active_record/database_configurations/database_config.rb +37 -0
 - data/lib/active_record/database_configurations/hash_config.rb +50 -0
 - data/lib/active_record/database_configurations/url_config.rb +79 -0
 - data/lib/active_record/dynamic_matchers.rb +1 -1
 - data/lib/active_record/enum.rb +37 -7
 - data/lib/active_record/errors.rb +15 -7
 - data/lib/active_record/explain.rb +1 -1
 - data/lib/active_record/fixture_set/model_metadata.rb +33 -0
 - data/lib/active_record/fixture_set/render_context.rb +17 -0
 - data/lib/active_record/fixture_set/table_row.rb +153 -0
 - data/lib/active_record/fixture_set/table_rows.rb +47 -0
 - data/lib/active_record/fixtures.rb +145 -472
 - data/lib/active_record/gem_version.rb +4 -4
 - data/lib/active_record/inheritance.rb +13 -3
 - data/lib/active_record/insert_all.rb +179 -0
 - data/lib/active_record/integration.rb +68 -16
 - data/lib/active_record/internal_metadata.rb +10 -2
 - data/lib/active_record/locking/optimistic.rb +5 -6
 - data/lib/active_record/locking/pessimistic.rb +3 -3
 - data/lib/active_record/log_subscriber.rb +7 -26
 - data/lib/active_record/middleware/database_selector.rb +75 -0
 - data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
 - data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
 - data/lib/active_record/migration.rb +100 -81
 - data/lib/active_record/migration/command_recorder.rb +50 -6
 - data/lib/active_record/migration/compatibility.rb +76 -49
 - data/lib/active_record/model_schema.rb +30 -9
 - data/lib/active_record/nested_attributes.rb +2 -2
 - data/lib/active_record/no_touching.rb +7 -0
 - data/lib/active_record/persistence.rb +228 -24
 - data/lib/active_record/query_cache.rb +11 -4
 - data/lib/active_record/querying.rb +32 -20
 - data/lib/active_record/railtie.rb +80 -43
 - data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
 - data/lib/active_record/railties/controller_runtime.rb +30 -35
 - data/lib/active_record/railties/databases.rake +196 -46
 - data/lib/active_record/reflection.rb +32 -30
 - data/lib/active_record/relation.rb +310 -80
 - data/lib/active_record/relation/batches.rb +13 -10
 - data/lib/active_record/relation/calculations.rb +53 -47
 - data/lib/active_record/relation/delegation.rb +26 -43
 - data/lib/active_record/relation/finder_methods.rb +13 -26
 - data/lib/active_record/relation/merger.rb +11 -20
 - data/lib/active_record/relation/predicate_builder.rb +4 -6
 - data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
 - data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
 - data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
 - data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
 - data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
 - data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
 - data/lib/active_record/relation/query_attribute.rb +13 -8
 - data/lib/active_record/relation/query_methods.rb +189 -63
 - data/lib/active_record/relation/spawn_methods.rb +1 -1
 - data/lib/active_record/relation/where_clause.rb +14 -10
 - data/lib/active_record/relation/where_clause_factory.rb +1 -2
 - data/lib/active_record/result.rb +30 -11
 - data/lib/active_record/sanitization.rb +32 -40
 - data/lib/active_record/schema.rb +2 -11
 - data/lib/active_record/schema_dumper.rb +22 -7
 - data/lib/active_record/schema_migration.rb +5 -1
 - data/lib/active_record/scoping.rb +8 -8
 - data/lib/active_record/scoping/default.rb +4 -5
 - data/lib/active_record/scoping/named.rb +19 -15
 - data/lib/active_record/statement_cache.rb +30 -3
 - data/lib/active_record/store.rb +87 -8
 - data/lib/active_record/table_metadata.rb +10 -17
 - data/lib/active_record/tasks/database_tasks.rb +194 -25
 - data/lib/active_record/tasks/mysql_database_tasks.rb +5 -5
 - data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -7
 - data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -8
 - data/lib/active_record/test_databases.rb +23 -0
 - data/lib/active_record/test_fixtures.rb +224 -0
 - data/lib/active_record/timestamp.rb +39 -25
 - data/lib/active_record/touch_later.rb +4 -2
 - data/lib/active_record/transactions.rb +57 -66
 - data/lib/active_record/translation.rb +1 -1
 - data/lib/active_record/type.rb +3 -4
 - data/lib/active_record/type/adapter_specific_registry.rb +1 -8
 - data/lib/active_record/type_caster/connection.rb +15 -14
 - data/lib/active_record/type_caster/map.rb +1 -4
 - data/lib/active_record/validations.rb +1 -0
 - data/lib/active_record/validations/uniqueness.rb +15 -27
 - data/lib/arel.rb +51 -0
 - data/lib/arel/alias_predication.rb +9 -0
 - data/lib/arel/attributes.rb +22 -0
 - data/lib/arel/attributes/attribute.rb +37 -0
 - data/lib/arel/collectors/bind.rb +24 -0
 - data/lib/arel/collectors/composite.rb +31 -0
 - data/lib/arel/collectors/plain_string.rb +20 -0
 - data/lib/arel/collectors/sql_string.rb +20 -0
 - data/lib/arel/collectors/substitute_binds.rb +28 -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.rb +68 -0
 - data/lib/arel/nodes/and.rb +32 -0
 - data/lib/arel/nodes/ascending.rb +23 -0
 - data/lib/arel/nodes/binary.rb +52 -0
 - data/lib/arel/nodes/bind_param.rb +36 -0
 - data/lib/arel/nodes/case.rb +55 -0
 - data/lib/arel/nodes/casted.rb +50 -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 +18 -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 +8 -0
 - data/lib/arel/nodes/in.rb +8 -0
 - data/lib/arel/nodes/infix_operation.rb +80 -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 +50 -0
 - data/lib/arel/nodes/node_expression.rb +13 -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 +16 -0
 - data/lib/arel/nodes/string_join.rb +11 -0
 - data/lib/arel/nodes/table_alias.rb +27 -0
 - data/lib/arel/nodes/terminal.rb +16 -0
 - data/lib/arel/nodes/true.rb +16 -0
 - data/lib/arel/nodes/unary.rb +45 -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/order_predications.rb +13 -0
 - data/lib/arel/predications.rb +257 -0
 - data/lib/arel/select_manager.rb +271 -0
 - data/lib/arel/table.rb +110 -0
 - data/lib/arel/tree_manager.rb +72 -0
 - data/lib/arel/update_manager.rb +34 -0
 - data/lib/arel/visitors.rb +20 -0
 - data/lib/arel/visitors/depth_first.rb +204 -0
 - data/lib/arel/visitors/dot.rb +297 -0
 - data/lib/arel/visitors/ibm_db.rb +34 -0
 - data/lib/arel/visitors/informix.rb +62 -0
 - data/lib/arel/visitors/mssql.rb +157 -0
 - data/lib/arel/visitors/mysql.rb +83 -0
 - data/lib/arel/visitors/oracle.rb +159 -0
 - data/lib/arel/visitors/oracle12.rb +66 -0
 - data/lib/arel/visitors/postgresql.rb +110 -0
 - data/lib/arel/visitors/sqlite.rb +39 -0
 - data/lib/arel/visitors/to_sql.rb +889 -0
 - data/lib/arel/visitors/visitor.rb +46 -0
 - data/lib/arel/visitors/where_sql.rb +23 -0
 - data/lib/arel/window_predications.rb +9 -0
 - data/lib/rails/generators/active_record/migration.rb +14 -1
 - data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
 - data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +1 -1
 - data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -2
 - data/lib/rails/generators/active_record/model/model_generator.rb +1 -0
 - data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
 - metadata +108 -26
 - data/lib/active_record/collection_cache_key.rb +0 -53
 
| 
         @@ -0,0 +1,75 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "active_record/middleware/database_selector/resolver"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module ActiveRecord
         
     | 
| 
      
 6 
     | 
    
         
            +
              module Middleware
         
     | 
| 
      
 7 
     | 
    
         
            +
                # The DatabaseSelector Middleware provides a framework for automatically
         
     | 
| 
      
 8 
     | 
    
         
            +
                # swapping from the primary to the replica database connection. Rails
         
     | 
| 
      
 9 
     | 
    
         
            +
                # provides a basic framework to determine when to swap and allows for
         
     | 
| 
      
 10 
     | 
    
         
            +
                # applications to write custom strategy classes to override the default
         
     | 
| 
      
 11 
     | 
    
         
            +
                # behavior.
         
     | 
| 
      
 12 
     | 
    
         
            +
                #
         
     | 
| 
      
 13 
     | 
    
         
            +
                # The resolver class defines when the application should switch (i.e. read
         
     | 
| 
      
 14 
     | 
    
         
            +
                # from the primary if a write occurred less than 2 seconds ago) and a
         
     | 
| 
      
 15 
     | 
    
         
            +
                # resolver context class that sets a value that helps the resolver class
         
     | 
| 
      
 16 
     | 
    
         
            +
                # decide when to switch.
         
     | 
| 
      
 17 
     | 
    
         
            +
                #
         
     | 
| 
      
 18 
     | 
    
         
            +
                # Rails default middleware uses the request's session to set a timestamp
         
     | 
| 
      
 19 
     | 
    
         
            +
                # that informs the application when to read from a primary or read from a
         
     | 
| 
      
 20 
     | 
    
         
            +
                # replica.
         
     | 
| 
      
 21 
     | 
    
         
            +
                #
         
     | 
| 
      
 22 
     | 
    
         
            +
                # To use the DatabaseSelector in your application with default settings add
         
     | 
| 
      
 23 
     | 
    
         
            +
                # the following options to your environment config:
         
     | 
| 
      
 24 
     | 
    
         
            +
                #
         
     | 
| 
      
 25 
     | 
    
         
            +
                #   config.active_record.database_selector = { delay: 2.seconds }
         
     | 
| 
      
 26 
     | 
    
         
            +
                #   config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
         
     | 
| 
      
 27 
     | 
    
         
            +
                #   config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
         
     | 
| 
      
 28 
     | 
    
         
            +
                #
         
     | 
| 
      
 29 
     | 
    
         
            +
                # New applications will include these lines commented out in the production.rb.
         
     | 
| 
      
 30 
     | 
    
         
            +
                #
         
     | 
| 
      
 31 
     | 
    
         
            +
                # The default behavior can be changed by setting the config options to a
         
     | 
| 
      
 32 
     | 
    
         
            +
                # custom class:
         
     | 
| 
      
 33 
     | 
    
         
            +
                #
         
     | 
| 
      
 34 
     | 
    
         
            +
                #   config.active_record.database_selector = { delay: 2.seconds }
         
     | 
| 
      
 35 
     | 
    
         
            +
                #   config.active_record.database_resolver = MyResolver
         
     | 
| 
      
 36 
     | 
    
         
            +
                #   config.active_record.database_resolver_context = MyResolver::MySession
         
     | 
| 
      
 37 
     | 
    
         
            +
                class DatabaseSelector
         
     | 
| 
      
 38 
     | 
    
         
            +
                  def initialize(app, resolver_klass = nil, context_klass = nil, options = {})
         
     | 
| 
      
 39 
     | 
    
         
            +
                    @app = app
         
     | 
| 
      
 40 
     | 
    
         
            +
                    @resolver_klass = resolver_klass || Resolver
         
     | 
| 
      
 41 
     | 
    
         
            +
                    @context_klass = context_klass || Resolver::Session
         
     | 
| 
      
 42 
     | 
    
         
            +
                    @options = options
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  attr_reader :resolver_klass, :context_klass, :options
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  # Middleware that determines which database connection to use in a multiple
         
     | 
| 
      
 48 
     | 
    
         
            +
                  # database application.
         
     | 
| 
      
 49 
     | 
    
         
            +
                  def call(env)
         
     | 
| 
      
 50 
     | 
    
         
            +
                    request = ActionDispatch::Request.new(env)
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                    select_database(request) do
         
     | 
| 
      
 53 
     | 
    
         
            +
                      @app.call(env)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    end
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                  private
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                    def select_database(request, &blk)
         
     | 
| 
      
 60 
     | 
    
         
            +
                      context = context_klass.call(request)
         
     | 
| 
      
 61 
     | 
    
         
            +
                      resolver = resolver_klass.call(context, options)
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                      if reading_request?(request)
         
     | 
| 
      
 64 
     | 
    
         
            +
                        resolver.read(&blk)
         
     | 
| 
      
 65 
     | 
    
         
            +
                      else
         
     | 
| 
      
 66 
     | 
    
         
            +
                        resolver.write(&blk)
         
     | 
| 
      
 67 
     | 
    
         
            +
                      end
         
     | 
| 
      
 68 
     | 
    
         
            +
                    end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                    def reading_request?(request)
         
     | 
| 
      
 71 
     | 
    
         
            +
                      request.get? || request.head?
         
     | 
| 
      
 72 
     | 
    
         
            +
                    end
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
              end
         
     | 
| 
      
 75 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,92 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "active_record/middleware/database_selector/resolver/session"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module ActiveRecord
         
     | 
| 
      
 6 
     | 
    
         
            +
              module Middleware
         
     | 
| 
      
 7 
     | 
    
         
            +
                class DatabaseSelector
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # The Resolver class is used by the DatabaseSelector middleware to
         
     | 
| 
      
 9 
     | 
    
         
            +
                  # determine which database the request should use.
         
     | 
| 
      
 10 
     | 
    
         
            +
                  #
         
     | 
| 
      
 11 
     | 
    
         
            +
                  # To change the behavior of the Resolver class in your application,
         
     | 
| 
      
 12 
     | 
    
         
            +
                  # create a custom resolver class that inherits from
         
     | 
| 
      
 13 
     | 
    
         
            +
                  # DatabaseSelector::Resolver and implements the methods that need to
         
     | 
| 
      
 14 
     | 
    
         
            +
                  # be changed.
         
     | 
| 
      
 15 
     | 
    
         
            +
                  #
         
     | 
| 
      
 16 
     | 
    
         
            +
                  # By default the Resolver class will send read traffic to the replica
         
     | 
| 
      
 17 
     | 
    
         
            +
                  # if it's been 2 seconds since the last write.
         
     | 
| 
      
 18 
     | 
    
         
            +
                  class Resolver # :nodoc:
         
     | 
| 
      
 19 
     | 
    
         
            +
                    SEND_TO_REPLICA_DELAY = 2.seconds
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                    def self.call(context, options = {})
         
     | 
| 
      
 22 
     | 
    
         
            +
                      new(context, options)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                    def initialize(context, options = {})
         
     | 
| 
      
 26 
     | 
    
         
            +
                      @context = context
         
     | 
| 
      
 27 
     | 
    
         
            +
                      @options = options
         
     | 
| 
      
 28 
     | 
    
         
            +
                      @delay = @options && @options[:delay] ? @options[:delay] : SEND_TO_REPLICA_DELAY
         
     | 
| 
      
 29 
     | 
    
         
            +
                      @instrumenter = ActiveSupport::Notifications.instrumenter
         
     | 
| 
      
 30 
     | 
    
         
            +
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                    attr_reader :context, :delay, :instrumenter
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    def read(&blk)
         
     | 
| 
      
 35 
     | 
    
         
            +
                      if read_from_primary?
         
     | 
| 
      
 36 
     | 
    
         
            +
                        read_from_primary(&blk)
         
     | 
| 
      
 37 
     | 
    
         
            +
                      else
         
     | 
| 
      
 38 
     | 
    
         
            +
                        read_from_replica(&blk)
         
     | 
| 
      
 39 
     | 
    
         
            +
                      end
         
     | 
| 
      
 40 
     | 
    
         
            +
                    end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                    def write(&blk)
         
     | 
| 
      
 43 
     | 
    
         
            +
                      write_to_primary(&blk)
         
     | 
| 
      
 44 
     | 
    
         
            +
                    end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                    private
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                      def read_from_primary(&blk)
         
     | 
| 
      
 49 
     | 
    
         
            +
                        ActiveRecord::Base.connected_to(role: ActiveRecord::Base.writing_role) do
         
     | 
| 
      
 50 
     | 
    
         
            +
                          ActiveRecord::Base.connection_handler.while_preventing_writes(true) do
         
     | 
| 
      
 51 
     | 
    
         
            +
                            instrumenter.instrument("database_selector.active_record.read_from_primary") do
         
     | 
| 
      
 52 
     | 
    
         
            +
                              yield
         
     | 
| 
      
 53 
     | 
    
         
            +
                            end
         
     | 
| 
      
 54 
     | 
    
         
            +
                          end
         
     | 
| 
      
 55 
     | 
    
         
            +
                        end
         
     | 
| 
      
 56 
     | 
    
         
            +
                      end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                      def read_from_replica(&blk)
         
     | 
| 
      
 59 
     | 
    
         
            +
                        ActiveRecord::Base.connected_to(role: ActiveRecord::Base.reading_role) do
         
     | 
| 
      
 60 
     | 
    
         
            +
                          instrumenter.instrument("database_selector.active_record.read_from_replica") do
         
     | 
| 
      
 61 
     | 
    
         
            +
                            yield
         
     | 
| 
      
 62 
     | 
    
         
            +
                          end
         
     | 
| 
      
 63 
     | 
    
         
            +
                        end
         
     | 
| 
      
 64 
     | 
    
         
            +
                      end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                      def write_to_primary(&blk)
         
     | 
| 
      
 67 
     | 
    
         
            +
                        ActiveRecord::Base.connected_to(role: ActiveRecord::Base.writing_role) do
         
     | 
| 
      
 68 
     | 
    
         
            +
                          ActiveRecord::Base.connection_handler.while_preventing_writes(false) do
         
     | 
| 
      
 69 
     | 
    
         
            +
                            instrumenter.instrument("database_selector.active_record.wrote_to_primary") do
         
     | 
| 
      
 70 
     | 
    
         
            +
                              yield
         
     | 
| 
      
 71 
     | 
    
         
            +
                            ensure
         
     | 
| 
      
 72 
     | 
    
         
            +
                              context.update_last_write_timestamp
         
     | 
| 
      
 73 
     | 
    
         
            +
                            end
         
     | 
| 
      
 74 
     | 
    
         
            +
                          end
         
     | 
| 
      
 75 
     | 
    
         
            +
                        end
         
     | 
| 
      
 76 
     | 
    
         
            +
                      end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                      def read_from_primary?
         
     | 
| 
      
 79 
     | 
    
         
            +
                        !time_since_last_write_ok?
         
     | 
| 
      
 80 
     | 
    
         
            +
                      end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                      def send_to_replica_delay
         
     | 
| 
      
 83 
     | 
    
         
            +
                        delay
         
     | 
| 
      
 84 
     | 
    
         
            +
                      end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                      def time_since_last_write_ok?
         
     | 
| 
      
 87 
     | 
    
         
            +
                        Time.now - context.last_write_timestamp >= send_to_replica_delay
         
     | 
| 
      
 88 
     | 
    
         
            +
                      end
         
     | 
| 
      
 89 
     | 
    
         
            +
                  end
         
     | 
| 
      
 90 
     | 
    
         
            +
                end
         
     | 
| 
      
 91 
     | 
    
         
            +
              end
         
     | 
| 
      
 92 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,45 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module ActiveRecord
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Middleware
         
     | 
| 
      
 5 
     | 
    
         
            +
                class DatabaseSelector
         
     | 
| 
      
 6 
     | 
    
         
            +
                  class Resolver
         
     | 
| 
      
 7 
     | 
    
         
            +
                    # The session class is used by the DatabaseSelector::Resolver to save
         
     | 
| 
      
 8 
     | 
    
         
            +
                    # timestamps of the last write in the session.
         
     | 
| 
      
 9 
     | 
    
         
            +
                    #
         
     | 
| 
      
 10 
     | 
    
         
            +
                    # The last_write is used to determine whether it's safe to read
         
     | 
| 
      
 11 
     | 
    
         
            +
                    # from the replica or the request needs to be sent to the primary.
         
     | 
| 
      
 12 
     | 
    
         
            +
                    class Session # :nodoc:
         
     | 
| 
      
 13 
     | 
    
         
            +
                      def self.call(request)
         
     | 
| 
      
 14 
     | 
    
         
            +
                        new(request.session)
         
     | 
| 
      
 15 
     | 
    
         
            +
                      end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                      # Converts time to a timestamp that represents milliseconds since
         
     | 
| 
      
 18 
     | 
    
         
            +
                      # epoch.
         
     | 
| 
      
 19 
     | 
    
         
            +
                      def self.convert_time_to_timestamp(time)
         
     | 
| 
      
 20 
     | 
    
         
            +
                        time.to_i * 1000 + time.usec / 1000
         
     | 
| 
      
 21 
     | 
    
         
            +
                      end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                      # Converts milliseconds since epoch timestamp into a time object.
         
     | 
| 
      
 24 
     | 
    
         
            +
                      def self.convert_timestamp_to_time(timestamp)
         
     | 
| 
      
 25 
     | 
    
         
            +
                        timestamp ? Time.at(timestamp / 1000, (timestamp % 1000) * 1000) : Time.at(0)
         
     | 
| 
      
 26 
     | 
    
         
            +
                      end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                      def initialize(session)
         
     | 
| 
      
 29 
     | 
    
         
            +
                        @session = session
         
     | 
| 
      
 30 
     | 
    
         
            +
                      end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                      attr_reader :session
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                      def last_write_timestamp
         
     | 
| 
      
 35 
     | 
    
         
            +
                        self.class.convert_timestamp_to_time(session[:last_write])
         
     | 
| 
      
 36 
     | 
    
         
            +
                      end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                      def update_last_write_timestamp
         
     | 
| 
      
 39 
     | 
    
         
            +
                        session[:last_write] = self.class.convert_time_to_timestamp(Time.now)
         
     | 
| 
      
 40 
     | 
    
         
            +
                      end
         
     | 
| 
      
 41 
     | 
    
         
            +
                    end
         
     | 
| 
      
 42 
     | 
    
         
            +
                  end
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
              end
         
     | 
| 
      
 45 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,11 +1,13 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
      
 3 
     | 
    
         
            +
            require "benchmark"
         
     | 
| 
       3 
4 
     | 
    
         
             
            require "set"
         
     | 
| 
       4 
5 
     | 
    
         
             
            require "zlib"
         
     | 
| 
       5 
6 
     | 
    
         
             
            require "active_support/core_ext/module/attribute_accessors"
         
     | 
| 
      
 7 
     | 
    
         
            +
            require "active_support/actionable_error"
         
     | 
| 
       6 
8 
     | 
    
         | 
| 
       7 
9 
     | 
    
         
             
            module ActiveRecord
         
     | 
| 
       8 
     | 
    
         
            -
              class MigrationError < ActiveRecordError#:nodoc:
         
     | 
| 
      
 10 
     | 
    
         
            +
              class MigrationError < ActiveRecordError #:nodoc:
         
     | 
| 
       9 
11 
     | 
    
         
             
                def initialize(message = nil)
         
     | 
| 
       10 
12 
     | 
    
         
             
                  message = "\n\n#{message}\n\n" if message
         
     | 
| 
       11 
13 
     | 
    
         
             
                  super
         
     | 
| 
         @@ -22,7 +24,7 @@ module ActiveRecord 
     | 
|
| 
       22 
24 
     | 
    
         
             
              #         t.string :zipcode
         
     | 
| 
       23 
25 
     | 
    
         
             
              #       end
         
     | 
| 
       24 
26 
     | 
    
         
             
              #
         
     | 
| 
       25 
     | 
    
         
            -
              #       execute  
     | 
| 
      
 27 
     | 
    
         
            +
              #       execute <<~SQL
         
     | 
| 
       26 
28 
     | 
    
         
             
              #         ALTER TABLE distributors
         
     | 
| 
       27 
29 
     | 
    
         
             
              #           ADD CONSTRAINT zipchk
         
     | 
| 
       28 
30 
     | 
    
         
             
              #             CHECK (char_length(zipcode) = 5) NO INHERIT;
         
     | 
| 
         @@ -40,7 +42,7 @@ module ActiveRecord 
     | 
|
| 
       40 
42 
     | 
    
         
             
              #        t.string :zipcode
         
     | 
| 
       41 
43 
     | 
    
         
             
              #      end
         
     | 
| 
       42 
44 
     | 
    
         
             
              #
         
     | 
| 
       43 
     | 
    
         
            -
              #      execute  
     | 
| 
      
 45 
     | 
    
         
            +
              #      execute <<~SQL
         
     | 
| 
       44 
46 
     | 
    
         
             
              #        ALTER TABLE distributors
         
     | 
| 
       45 
47 
     | 
    
         
             
              #          ADD CONSTRAINT zipchk
         
     | 
| 
       46 
48 
     | 
    
         
             
              #            CHECK (char_length(zipcode) = 5) NO INHERIT;
         
     | 
| 
         @@ -48,7 +50,7 @@ module ActiveRecord 
     | 
|
| 
       48 
50 
     | 
    
         
             
              #    end
         
     | 
| 
       49 
51 
     | 
    
         
             
              #
         
     | 
| 
       50 
52 
     | 
    
         
             
              #    def down
         
     | 
| 
       51 
     | 
    
         
            -
              #      execute  
     | 
| 
      
 53 
     | 
    
         
            +
              #      execute <<~SQL
         
     | 
| 
       52 
54 
     | 
    
         
             
              #        ALTER TABLE distributors
         
     | 
| 
       53 
55 
     | 
    
         
             
              #          DROP CONSTRAINT zipchk
         
     | 
| 
       54 
56 
     | 
    
         
             
              #      SQL
         
     | 
| 
         @@ -67,7 +69,7 @@ module ActiveRecord 
     | 
|
| 
       67 
69 
     | 
    
         
             
              #
         
     | 
| 
       68 
70 
     | 
    
         
             
              #       reversible do |dir|
         
     | 
| 
       69 
71 
     | 
    
         
             
              #         dir.up do
         
     | 
| 
       70 
     | 
    
         
            -
              #           execute  
     | 
| 
      
 72 
     | 
    
         
            +
              #           execute <<~SQL
         
     | 
| 
       71 
73 
     | 
    
         
             
              #             ALTER TABLE distributors
         
     | 
| 
       72 
74 
     | 
    
         
             
              #               ADD CONSTRAINT zipchk
         
     | 
| 
       73 
75 
     | 
    
         
             
              #                 CHECK (char_length(zipcode) = 5) NO INHERIT;
         
     | 
| 
         @@ -75,7 +77,7 @@ module ActiveRecord 
     | 
|
| 
       75 
77 
     | 
    
         
             
              #         end
         
     | 
| 
       76 
78 
     | 
    
         
             
              #
         
     | 
| 
       77 
79 
     | 
    
         
             
              #         dir.down do
         
     | 
| 
       78 
     | 
    
         
            -
              #           execute  
     | 
| 
      
 80 
     | 
    
         
            +
              #           execute <<~SQL
         
     | 
| 
       79 
81 
     | 
    
         
             
              #             ALTER TABLE distributors
         
     | 
| 
       80 
82 
     | 
    
         
             
              #               DROP CONSTRAINT zipchk
         
     | 
| 
       81 
83 
     | 
    
         
             
              #           SQL
         
     | 
| 
         @@ -86,7 +88,7 @@ module ActiveRecord 
     | 
|
| 
       86 
88 
     | 
    
         
             
              class IrreversibleMigration < MigrationError
         
     | 
| 
       87 
89 
     | 
    
         
             
              end
         
     | 
| 
       88 
90 
     | 
    
         | 
| 
       89 
     | 
    
         
            -
              class DuplicateMigrationVersionError < MigrationError#:nodoc:
         
     | 
| 
      
 91 
     | 
    
         
            +
              class DuplicateMigrationVersionError < MigrationError #:nodoc:
         
     | 
| 
       90 
92 
     | 
    
         
             
                def initialize(version = nil)
         
     | 
| 
       91 
93 
     | 
    
         
             
                  if version
         
     | 
| 
       92 
94 
     | 
    
         
             
                    super("Multiple migrations have the version number #{version}.")
         
     | 
| 
         @@ -96,7 +98,7 @@ module ActiveRecord 
     | 
|
| 
       96 
98 
     | 
    
         
             
                end
         
     | 
| 
       97 
99 
     | 
    
         
             
              end
         
     | 
| 
       98 
100 
     | 
    
         | 
| 
       99 
     | 
    
         
            -
              class DuplicateMigrationNameError < MigrationError#:nodoc:
         
     | 
| 
      
 101 
     | 
    
         
            +
              class DuplicateMigrationNameError < MigrationError #:nodoc:
         
     | 
| 
       100 
102 
     | 
    
         
             
                def initialize(name = nil)
         
     | 
| 
       101 
103 
     | 
    
         
             
                  if name
         
     | 
| 
       102 
104 
     | 
    
         
             
                    super("Multiple migrations have the name #{name}.")
         
     | 
| 
         @@ -116,7 +118,7 @@ module ActiveRecord 
     | 
|
| 
       116 
118 
     | 
    
         
             
                end
         
     | 
| 
       117 
119 
     | 
    
         
             
              end
         
     | 
| 
       118 
120 
     | 
    
         | 
| 
       119 
     | 
    
         
            -
              class IllegalMigrationNameError < MigrationError#:nodoc:
         
     | 
| 
      
 121 
     | 
    
         
            +
              class IllegalMigrationNameError < MigrationError #:nodoc:
         
     | 
| 
       120 
122 
     | 
    
         
             
                def initialize(name = nil)
         
     | 
| 
       121 
123 
     | 
    
         
             
                  if name
         
     | 
| 
       122 
124 
     | 
    
         
             
                    super("Illegal name for migration file: #{name}\n\t(only lower case letters, numbers, and '_' allowed).")
         
     | 
| 
         @@ -126,12 +128,18 @@ module ActiveRecord 
     | 
|
| 
       126 
128 
     | 
    
         
             
                end
         
     | 
| 
       127 
129 
     | 
    
         
             
              end
         
     | 
| 
       128 
130 
     | 
    
         | 
| 
       129 
     | 
    
         
            -
              class PendingMigrationError < MigrationError#:nodoc:
         
     | 
| 
      
 131 
     | 
    
         
            +
              class PendingMigrationError < MigrationError #:nodoc:
         
     | 
| 
      
 132 
     | 
    
         
            +
                include ActiveSupport::ActionableError
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
                action "Run pending migrations" do
         
     | 
| 
      
 135 
     | 
    
         
            +
                  ActiveRecord::Tasks::DatabaseTasks.migrate
         
     | 
| 
      
 136 
     | 
    
         
            +
                end
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
       130 
138 
     | 
    
         
             
                def initialize(message = nil)
         
     | 
| 
       131 
139 
     | 
    
         
             
                  if !message && defined?(Rails.env)
         
     | 
| 
       132 
     | 
    
         
            -
                    super("Migrations are pending. To resolve this issue, run:\n\n         
     | 
| 
      
 140 
     | 
    
         
            +
                    super("Migrations are pending. To resolve this issue, run:\n\n        rails db:migrate RAILS_ENV=#{::Rails.env}")
         
     | 
| 
       133 
141 
     | 
    
         
             
                  elsif !message
         
     | 
| 
       134 
     | 
    
         
            -
                    super("Migrations are pending. To resolve this issue, run:\n\n         
     | 
| 
      
 142 
     | 
    
         
            +
                    super("Migrations are pending. To resolve this issue, run:\n\n        rails db:migrate")
         
     | 
| 
       135 
143 
     | 
    
         
             
                  else
         
     | 
| 
       136 
144 
     | 
    
         
             
                    super
         
     | 
| 
       137 
145 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -139,8 +147,8 @@ module ActiveRecord 
     | 
|
| 
       139 
147 
     | 
    
         
             
              end
         
     | 
| 
       140 
148 
     | 
    
         | 
| 
       141 
149 
     | 
    
         
             
              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" 
     | 
| 
      
 150 
     | 
    
         
            +
                DEFAULT_MESSAGE = "Cannot run migrations because another migration process is currently running."
         
     | 
| 
      
 151 
     | 
    
         
            +
                RELEASE_LOCK_FAILED_MESSAGE = "Failed to release advisory lock"
         
     | 
| 
       144 
152 
     | 
    
         | 
| 
       145 
153 
     | 
    
         
             
                def initialize(message = DEFAULT_MESSAGE)
         
     | 
| 
       146 
154 
     | 
    
         
             
                  super
         
     | 
| 
         @@ -149,7 +157,7 @@ module ActiveRecord 
     | 
|
| 
       149 
157 
     | 
    
         | 
| 
       150 
158 
     | 
    
         
             
              class NoEnvironmentInSchemaError < MigrationError #:nodoc:
         
     | 
| 
       151 
159 
     | 
    
         
             
                def initialize
         
     | 
| 
       152 
     | 
    
         
            -
                  msg = "Environment data not found in the schema. To resolve this issue, run: \n\n         
     | 
| 
      
 160 
     | 
    
         
            +
                  msg = "Environment data not found in the schema. To resolve this issue, run: \n\n        rails db:environment:set"
         
     | 
| 
       153 
161 
     | 
    
         
             
                  if defined?(Rails.env)
         
     | 
| 
       154 
162 
     | 
    
         
             
                    super("#{msg} RAILS_ENV=#{::Rails.env}")
         
     | 
| 
       155 
163 
     | 
    
         
             
                  else
         
     | 
| 
         @@ -160,7 +168,7 @@ module ActiveRecord 
     | 
|
| 
       160 
168 
     | 
    
         | 
| 
       161 
169 
     | 
    
         
             
              class ProtectedEnvironmentError < ActiveRecordError #:nodoc:
         
     | 
| 
       162 
170 
     | 
    
         
             
                def initialize(env = "production")
         
     | 
| 
       163 
     | 
    
         
            -
                  msg = "You are attempting to run a destructive action against your '#{env}' database.\n" 
     | 
| 
      
 171 
     | 
    
         
            +
                  msg = +"You are attempting to run a destructive action against your '#{env}' database.\n"
         
     | 
| 
       164 
172 
     | 
    
         
             
                  msg << "If you are sure you want to continue, run the same command with the environment variable:\n"
         
     | 
| 
       165 
173 
     | 
    
         
             
                  msg << "DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
         
     | 
| 
       166 
174 
     | 
    
         
             
                  super(msg)
         
     | 
| 
         @@ -169,10 +177,10 @@ module ActiveRecord 
     | 
|
| 
       169 
177 
     | 
    
         | 
| 
       170 
178 
     | 
    
         
             
              class EnvironmentMismatchError < ActiveRecordError
         
     | 
| 
       171 
179 
     | 
    
         
             
                def initialize(current: nil, stored: nil)
         
     | 
| 
       172 
     | 
    
         
            -
                  msg = 
     | 
| 
      
 180 
     | 
    
         
            +
                  msg = +"You are attempting to modify a database that was last run in `#{ stored }` environment.\n"
         
     | 
| 
       173 
181 
     | 
    
         
             
                  msg << "You are running in `#{ current }` environment. "
         
     | 
| 
       174 
182 
     | 
    
         
             
                  msg << "If you are sure you want to continue, first set the environment using:\n\n"
         
     | 
| 
       175 
     | 
    
         
            -
                  msg << "         
     | 
| 
      
 183 
     | 
    
         
            +
                  msg << "        rails db:environment:set"
         
     | 
| 
       176 
184 
     | 
    
         
             
                  if defined?(Rails.env)
         
     | 
| 
       177 
185 
     | 
    
         
             
                    super("#{msg} RAILS_ENV=#{::Rails.env}\n\n")
         
     | 
| 
       178 
186 
     | 
    
         
             
                  else
         
     | 
| 
         @@ -307,7 +315,7 @@ module ActiveRecord 
     | 
|
| 
       307 
315 
     | 
    
         
             
              #   named +column_name+ from the table called +table_name+.
         
     | 
| 
       308 
316 
     | 
    
         
             
              # * <tt>remove_columns(table_name, *column_names)</tt>: Removes the given
         
     | 
| 
       309 
317 
     | 
    
         
             
              #   columns from the table definition.
         
     | 
| 
       310 
     | 
    
         
            -
              # * <tt>remove_foreign_key(from_table,  
     | 
| 
      
 318 
     | 
    
         
            +
              # * <tt>remove_foreign_key(from_table, to_table = nil, **options)</tt>: Removes the
         
     | 
| 
       311 
319 
     | 
    
         
             
              #   given foreign key from the table called +table_name+.
         
     | 
| 
       312 
320 
     | 
    
         
             
              # * <tt>remove_index(table_name, column: column_names)</tt>: Removes the index
         
     | 
| 
       313 
321 
     | 
    
         
             
              #   specified by +column_names+.
         
     | 
| 
         @@ -351,7 +359,7 @@ module ActiveRecord 
     | 
|
| 
       351 
359 
     | 
    
         
             
              # <tt>rails db:migrate</tt>. This will update the database by running all of the
         
     | 
| 
       352 
360 
     | 
    
         
             
              # pending migrations, creating the <tt>schema_migrations</tt> table
         
     | 
| 
       353 
361 
     | 
    
         
             
              # (see "About the schema_migrations table" section below) if missing. It will also
         
     | 
| 
       354 
     | 
    
         
            -
              # invoke the db:schema:dump  
     | 
| 
      
 362 
     | 
    
         
            +
              # invoke the db:schema:dump command, which will update your db/schema.rb file
         
     | 
| 
       355 
363 
     | 
    
         
             
              # to match the structure of your database.
         
     | 
| 
       356 
364 
     | 
    
         
             
              #
         
     | 
| 
       357 
365 
     | 
    
         
             
              # To roll the database back to a previous migration version, use
         
     | 
| 
         @@ -486,9 +494,9 @@ module ActiveRecord 
     | 
|
| 
       486 
494 
     | 
    
         
             
              # This migration will create the horses table for you on the way up, and
         
     | 
| 
       487 
495 
     | 
    
         
             
              # automatically figure out how to drop the table on the way down.
         
     | 
| 
       488 
496 
     | 
    
         
             
              #
         
     | 
| 
       489 
     | 
    
         
            -
              # Some commands  
     | 
| 
       490 
     | 
    
         
            -
              #  
     | 
| 
       491 
     | 
    
         
            -
              #  
     | 
| 
      
 497 
     | 
    
         
            +
              # Some commands cannot be reversed. If you care to define how to move up
         
     | 
| 
      
 498 
     | 
    
         
            +
              # and down in these cases, you should define the +up+ and +down+ methods
         
     | 
| 
      
 499 
     | 
    
         
            +
              # as before.
         
     | 
| 
       492 
500 
     | 
    
         
             
              #
         
     | 
| 
       493 
501 
     | 
    
         
             
              # If a command cannot be reversed, an
         
     | 
| 
       494 
502 
     | 
    
         
             
              # <tt>ActiveRecord::IrreversibleMigration</tt> exception will be raised when
         
     | 
| 
         @@ -519,10 +527,10 @@ module ActiveRecord 
     | 
|
| 
       519 
527 
     | 
    
         
             
                autoload :Compatibility, "active_record/migration/compatibility"
         
     | 
| 
       520 
528 
     | 
    
         | 
| 
       521 
529 
     | 
    
         
             
                # This must be defined before the inherited hook, below
         
     | 
| 
       522 
     | 
    
         
            -
                class Current < Migration  
     | 
| 
      
 530 
     | 
    
         
            +
                class Current < Migration #:nodoc:
         
     | 
| 
       523 
531 
     | 
    
         
             
                end
         
     | 
| 
       524 
532 
     | 
    
         | 
| 
       525 
     | 
    
         
            -
                def self.inherited(subclass)  
     | 
| 
      
 533 
     | 
    
         
            +
                def self.inherited(subclass) #:nodoc:
         
     | 
| 
       526 
534 
     | 
    
         
             
                  super
         
     | 
| 
       527 
535 
     | 
    
         
             
                  if subclass.superclass == Migration
         
     | 
| 
       528 
536 
     | 
    
         
             
                    raise StandardError, "Directly inheriting from ActiveRecord::Migration is not supported. " \
         
     | 
| 
         @@ -540,7 +548,7 @@ module ActiveRecord 
     | 
|
| 
       540 
548 
     | 
    
         
             
                  ActiveRecord::VERSION::STRING.to_f
         
     | 
| 
       541 
549 
     | 
    
         
             
                end
         
     | 
| 
       542 
550 
     | 
    
         | 
| 
       543 
     | 
    
         
            -
                MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/  
     | 
| 
      
 551 
     | 
    
         
            +
                MigrationFilenameRegexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/ #:nodoc:
         
     | 
| 
       544 
552 
     | 
    
         | 
| 
       545 
553 
     | 
    
         
             
                # This class is used to verify that all migrations have been run before
         
     | 
| 
       546 
554 
     | 
    
         
             
                # loading a web page if <tt>config.active_record.migration_error</tt> is set to :page_load
         
     | 
| 
         @@ -567,10 +575,10 @@ module ActiveRecord 
     | 
|
| 
       567 
575 
     | 
    
         
             
                end
         
     | 
| 
       568 
576 
     | 
    
         | 
| 
       569 
577 
     | 
    
         
             
                class << self
         
     | 
| 
       570 
     | 
    
         
            -
                  attr_accessor :delegate  
     | 
| 
       571 
     | 
    
         
            -
                  attr_accessor :disable_ddl_transaction  
     | 
| 
      
 578 
     | 
    
         
            +
                  attr_accessor :delegate #:nodoc:
         
     | 
| 
      
 579 
     | 
    
         
            +
                  attr_accessor :disable_ddl_transaction #:nodoc:
         
     | 
| 
       572 
580 
     | 
    
         | 
| 
       573 
     | 
    
         
            -
                  def nearest_delegate  
     | 
| 
      
 581 
     | 
    
         
            +
                  def nearest_delegate #:nodoc:
         
     | 
| 
       574 
582 
     | 
    
         
             
                    delegate || superclass.nearest_delegate
         
     | 
| 
       575 
583 
     | 
    
         
             
                  end
         
     | 
| 
       576 
584 
     | 
    
         | 
| 
         @@ -580,27 +588,35 @@ module ActiveRecord 
     | 
|
| 
       580 
588 
     | 
    
         
             
                  end
         
     | 
| 
       581 
589 
     | 
    
         | 
| 
       582 
590 
     | 
    
         
             
                  def load_schema_if_pending!
         
     | 
| 
       583 
     | 
    
         
            -
                     
     | 
| 
      
 591 
     | 
    
         
            +
                    current_config = Base.connection_config
         
     | 
| 
      
 592 
     | 
    
         
            +
                    all_configs = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env)
         
     | 
| 
      
 593 
     | 
    
         
            +
             
     | 
| 
      
 594 
     | 
    
         
            +
                    needs_update = !all_configs.all? do |db_config|
         
     | 
| 
      
 595 
     | 
    
         
            +
                      Tasks::DatabaseTasks.schema_up_to_date?(db_config.config, ActiveRecord::Base.schema_format, nil, Rails.env, db_config.spec_name)
         
     | 
| 
      
 596 
     | 
    
         
            +
                    end
         
     | 
| 
      
 597 
     | 
    
         
            +
             
     | 
| 
      
 598 
     | 
    
         
            +
                    if needs_update
         
     | 
| 
       584 
599 
     | 
    
         
             
                      # Roundtrip to Rake to allow plugins to hook into database initialization.
         
     | 
| 
       585 
600 
     | 
    
         
             
                      root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
         
     | 
| 
       586 
601 
     | 
    
         
             
                      FileUtils.cd(root) do
         
     | 
| 
       587 
     | 
    
         
            -
                        current_config = Base.connection_config
         
     | 
| 
       588 
602 
     | 
    
         
             
                        Base.clear_all_connections!
         
     | 
| 
       589 
603 
     | 
    
         
             
                        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 
604 
     | 
    
         
             
                      end
         
     | 
| 
       593 
     | 
    
         
            -
                      check_pending!
         
     | 
| 
       594 
605 
     | 
    
         
             
                    end
         
     | 
| 
      
 606 
     | 
    
         
            +
             
     | 
| 
      
 607 
     | 
    
         
            +
                    # Establish a new connection, the old database may be gone (db:test:prepare uses purge)
         
     | 
| 
      
 608 
     | 
    
         
            +
                    Base.establish_connection(current_config)
         
     | 
| 
      
 609 
     | 
    
         
            +
             
     | 
| 
      
 610 
     | 
    
         
            +
                    check_pending!
         
     | 
| 
       595 
611 
     | 
    
         
             
                  end
         
     | 
| 
       596 
612 
     | 
    
         | 
| 
       597 
     | 
    
         
            -
                  def maintain_test_schema!  
     | 
| 
      
 613 
     | 
    
         
            +
                  def maintain_test_schema! #:nodoc:
         
     | 
| 
       598 
614 
     | 
    
         
             
                    if ActiveRecord::Base.maintain_test_schema
         
     | 
| 
       599 
615 
     | 
    
         
             
                      suppress_messages { load_schema_if_pending! }
         
     | 
| 
       600 
616 
     | 
    
         
             
                    end
         
     | 
| 
       601 
617 
     | 
    
         
             
                  end
         
     | 
| 
       602 
618 
     | 
    
         | 
| 
       603 
     | 
    
         
            -
                  def method_missing(name, *args, &block)  
     | 
| 
      
 619 
     | 
    
         
            +
                  def method_missing(name, *args, &block) #:nodoc:
         
     | 
| 
       604 
620 
     | 
    
         
             
                    nearest_delegate.send(name, *args, &block)
         
     | 
| 
       605 
621 
     | 
    
         
             
                  end
         
     | 
| 
       606 
622 
     | 
    
         | 
| 
         @@ -617,7 +633,7 @@ module ActiveRecord 
     | 
|
| 
       617 
633 
     | 
    
         
             
                  end
         
     | 
| 
       618 
634 
     | 
    
         
             
                end
         
     | 
| 
       619 
635 
     | 
    
         | 
| 
       620 
     | 
    
         
            -
                def disable_ddl_transaction  
     | 
| 
      
 636 
     | 
    
         
            +
                def disable_ddl_transaction #:nodoc:
         
     | 
| 
       621 
637 
     | 
    
         
             
                  self.class.disable_ddl_transaction
         
     | 
| 
       622 
638 
     | 
    
         
             
                end
         
     | 
| 
       623 
639 
     | 
    
         | 
| 
         @@ -677,15 +693,13 @@ module ActiveRecord 
     | 
|
| 
       677 
693 
     | 
    
         
             
                    if connection.respond_to? :revert
         
     | 
| 
       678 
694 
     | 
    
         
             
                      connection.revert { yield }
         
     | 
| 
       679 
695 
     | 
    
         
             
                    else
         
     | 
| 
       680 
     | 
    
         
            -
                      recorder =  
     | 
| 
      
 696 
     | 
    
         
            +
                      recorder = command_recorder
         
     | 
| 
       681 
697 
     | 
    
         
             
                      @connection = recorder
         
     | 
| 
       682 
698 
     | 
    
         
             
                      suppress_messages do
         
     | 
| 
       683 
699 
     | 
    
         
             
                        connection.revert { yield }
         
     | 
| 
       684 
700 
     | 
    
         
             
                      end
         
     | 
| 
       685 
701 
     | 
    
         
             
                      @connection = recorder.delegate
         
     | 
| 
       686 
     | 
    
         
            -
                      recorder. 
     | 
| 
       687 
     | 
    
         
            -
                        send(cmd, *args, &block)
         
     | 
| 
       688 
     | 
    
         
            -
                      end
         
     | 
| 
      
 702 
     | 
    
         
            +
                      recorder.replay(self)
         
     | 
| 
       689 
703 
     | 
    
         
             
                    end
         
     | 
| 
       690 
704 
     | 
    
         
             
                  end
         
     | 
| 
       691 
705 
     | 
    
         
             
                end
         
     | 
| 
         @@ -694,7 +708,7 @@ module ActiveRecord 
     | 
|
| 
       694 
708 
     | 
    
         
             
                  connection.respond_to?(:reverting) && connection.reverting
         
     | 
| 
       695 
709 
     | 
    
         
             
                end
         
     | 
| 
       696 
710 
     | 
    
         | 
| 
       697 
     | 
    
         
            -
                ReversibleBlockHelper = Struct.new(:reverting) do  
     | 
| 
      
 711 
     | 
    
         
            +
                ReversibleBlockHelper = Struct.new(:reverting) do #:nodoc:
         
     | 
| 
       698 
712 
     | 
    
         
             
                  def up
         
     | 
| 
       699 
713 
     | 
    
         
             
                    yield unless reverting
         
     | 
| 
       700 
714 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -830,10 +844,14 @@ module ActiveRecord 
     | 
|
| 
       830 
844 
     | 
    
         
             
                  write "== %s %s" % [text, "=" * length]
         
     | 
| 
       831 
845 
     | 
    
         
             
                end
         
     | 
| 
       832 
846 
     | 
    
         | 
| 
      
 847 
     | 
    
         
            +
                # Takes a message argument and outputs it as is.
         
     | 
| 
      
 848 
     | 
    
         
            +
                # A second boolean argument can be passed to specify whether to indent or not.
         
     | 
| 
       833 
849 
     | 
    
         
             
                def say(message, subitem = false)
         
     | 
| 
       834 
850 
     | 
    
         
             
                  write "#{subitem ? "   ->" : "--"} #{message}"
         
     | 
| 
       835 
851 
     | 
    
         
             
                end
         
     | 
| 
       836 
852 
     | 
    
         | 
| 
      
 853 
     | 
    
         
            +
                # Outputs text along with how long it took to run its block.
         
     | 
| 
      
 854 
     | 
    
         
            +
                # If the block returns an integer it assumes it is the number of rows affected.
         
     | 
| 
       837 
855 
     | 
    
         
             
                def say_with_time(message)
         
     | 
| 
       838 
856 
     | 
    
         
             
                  say(message)
         
     | 
| 
       839 
857 
     | 
    
         
             
                  result = nil
         
     | 
| 
         @@ -843,6 +861,7 @@ module ActiveRecord 
     | 
|
| 
       843 
861 
     | 
    
         
             
                  result
         
     | 
| 
       844 
862 
     | 
    
         
             
                end
         
     | 
| 
       845 
863 
     | 
    
         | 
| 
      
 864 
     | 
    
         
            +
                # Takes a block as an argument and suppresses any output generated by the block.
         
     | 
| 
       846 
865 
     | 
    
         
             
                def suppress_messages
         
     | 
| 
       847 
866 
     | 
    
         
             
                  save, self.verbose = verbose, false
         
     | 
| 
       848 
867 
     | 
    
         
             
                  yield
         
     | 
| 
         @@ -874,18 +893,19 @@ module ActiveRecord 
     | 
|
| 
       874 
893 
     | 
    
         | 
| 
       875 
894 
     | 
    
         
             
                def copy(destination, sources, options = {})
         
     | 
| 
       876 
895 
     | 
    
         
             
                  copied = []
         
     | 
| 
      
 896 
     | 
    
         
            +
                  schema_migration = options[:schema_migration] || ActiveRecord::SchemaMigration
         
     | 
| 
       877 
897 
     | 
    
         | 
| 
       878 
898 
     | 
    
         
             
                  FileUtils.mkdir_p(destination) unless File.exist?(destination)
         
     | 
| 
       879 
899 
     | 
    
         | 
| 
       880 
     | 
    
         
            -
                  destination_migrations = ActiveRecord::MigrationContext.new(destination).migrations
         
     | 
| 
      
 900 
     | 
    
         
            +
                  destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration).migrations
         
     | 
| 
       881 
901 
     | 
    
         
             
                  last = destination_migrations.last
         
     | 
| 
       882 
902 
     | 
    
         
             
                  sources.each do |scope, path|
         
     | 
| 
       883 
     | 
    
         
            -
                    source_migrations = ActiveRecord::MigrationContext.new(path).migrations
         
     | 
| 
      
 903 
     | 
    
         
            +
                    source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration).migrations
         
     | 
| 
       884 
904 
     | 
    
         | 
| 
       885 
905 
     | 
    
         
             
                    source_migrations.each do |migration|
         
     | 
| 
       886 
906 
     | 
    
         
             
                      source = File.binread(migration.filename)
         
     | 
| 
       887 
907 
     | 
    
         
             
                      inserted_comment = "# This migration comes from #{scope} (originally #{migration.version})\n"
         
     | 
| 
       888 
     | 
    
         
            -
                      magic_comments = "" 
     | 
| 
      
 908 
     | 
    
         
            +
                      magic_comments = +""
         
     | 
| 
       889 
909 
     | 
    
         
             
                      loop do
         
     | 
| 
       890 
910 
     | 
    
         
             
                        # If we have a magic comment in the original migration,
         
     | 
| 
       891 
911 
     | 
    
         
             
                        # insert our comment after the first newline(end of the magic comment line)
         
     | 
| 
         @@ -956,6 +976,10 @@ module ActiveRecord 
     | 
|
| 
       956 
976 
     | 
    
         
             
                      yield
         
     | 
| 
       957 
977 
     | 
    
         
             
                    end
         
     | 
| 
       958 
978 
     | 
    
         
             
                  end
         
     | 
| 
      
 979 
     | 
    
         
            +
             
     | 
| 
      
 980 
     | 
    
         
            +
                  def command_recorder
         
     | 
| 
      
 981 
     | 
    
         
            +
                    CommandRecorder.new(connection)
         
     | 
| 
      
 982 
     | 
    
         
            +
                  end
         
     | 
| 
       959 
983 
     | 
    
         
             
              end
         
     | 
| 
       960 
984 
     | 
    
         | 
| 
       961 
985 
     | 
    
         
             
              # MigrationProxy is used to defer loading of the actual migration classes
         
     | 
| 
         @@ -998,11 +1022,12 @@ module ActiveRecord 
     | 
|
| 
       998 
1022 
     | 
    
         
             
                end
         
     | 
| 
       999 
1023 
     | 
    
         
             
              end
         
     | 
| 
       1000 
1024 
     | 
    
         | 
| 
       1001 
     | 
    
         
            -
              class MigrationContext  
     | 
| 
       1002 
     | 
    
         
            -
                attr_reader :migrations_paths
         
     | 
| 
      
 1025 
     | 
    
         
            +
              class MigrationContext #:nodoc:
         
     | 
| 
      
 1026 
     | 
    
         
            +
                attr_reader :migrations_paths, :schema_migration
         
     | 
| 
       1003 
1027 
     | 
    
         | 
| 
       1004 
     | 
    
         
            -
                def initialize(migrations_paths)
         
     | 
| 
      
 1028 
     | 
    
         
            +
                def initialize(migrations_paths, schema_migration)
         
     | 
| 
       1005 
1029 
     | 
    
         
             
                  @migrations_paths = migrations_paths
         
     | 
| 
      
 1030 
     | 
    
         
            +
                  @schema_migration = schema_migration
         
     | 
| 
       1006 
1031 
     | 
    
         
             
                end
         
     | 
| 
       1007 
1032 
     | 
    
         | 
| 
       1008 
1033 
     | 
    
         
             
                def migrate(target_version = nil, &block)
         
     | 
| 
         @@ -1033,7 +1058,7 @@ module ActiveRecord 
     | 
|
| 
       1033 
1058 
     | 
    
         
             
                    migrations
         
     | 
| 
       1034 
1059 
     | 
    
         
             
                  end
         
     | 
| 
       1035 
1060 
     | 
    
         | 
| 
       1036 
     | 
    
         
            -
                  Migrator.new(:up, selected_migrations, target_version).migrate
         
     | 
| 
      
 1061 
     | 
    
         
            +
                  Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate
         
     | 
| 
       1037 
1062 
     | 
    
         
             
                end
         
     | 
| 
       1038 
1063 
     | 
    
         | 
| 
       1039 
1064 
     | 
    
         
             
                def down(target_version = nil)
         
     | 
| 
         @@ -1043,20 +1068,20 @@ module ActiveRecord 
     | 
|
| 
       1043 
1068 
     | 
    
         
             
                    migrations
         
     | 
| 
       1044 
1069 
     | 
    
         
             
                  end
         
     | 
| 
       1045 
1070 
     | 
    
         | 
| 
       1046 
     | 
    
         
            -
                  Migrator.new(:down, selected_migrations, target_version).migrate
         
     | 
| 
      
 1071 
     | 
    
         
            +
                  Migrator.new(:down, selected_migrations, schema_migration, target_version).migrate
         
     | 
| 
       1047 
1072 
     | 
    
         
             
                end
         
     | 
| 
       1048 
1073 
     | 
    
         | 
| 
       1049 
1074 
     | 
    
         
             
                def run(direction, target_version)
         
     | 
| 
       1050 
     | 
    
         
            -
                  Migrator.new(direction, migrations, target_version).run
         
     | 
| 
      
 1075 
     | 
    
         
            +
                  Migrator.new(direction, migrations, schema_migration, target_version).run
         
     | 
| 
       1051 
1076 
     | 
    
         
             
                end
         
     | 
| 
       1052 
1077 
     | 
    
         | 
| 
       1053 
1078 
     | 
    
         
             
                def open
         
     | 
| 
       1054 
     | 
    
         
            -
                  Migrator.new(:up, migrations,  
     | 
| 
      
 1079 
     | 
    
         
            +
                  Migrator.new(:up, migrations, schema_migration)
         
     | 
| 
       1055 
1080 
     | 
    
         
             
                end
         
     | 
| 
       1056 
1081 
     | 
    
         | 
| 
       1057 
1082 
     | 
    
         
             
                def get_all_versions
         
     | 
| 
       1058 
     | 
    
         
            -
                  if  
     | 
| 
       1059 
     | 
    
         
            -
                     
     | 
| 
      
 1083 
     | 
    
         
            +
                  if schema_migration.table_exists?
         
     | 
| 
      
 1084 
     | 
    
         
            +
                    schema_migration.all_versions.map(&:to_i)
         
     | 
| 
       1060 
1085 
     | 
    
         
             
                  else
         
     | 
| 
       1061 
1086 
     | 
    
         
             
                    []
         
     | 
| 
       1062 
1087 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -1079,10 +1104,6 @@ module ActiveRecord 
     | 
|
| 
       1079 
1104 
     | 
    
         
             
                  migrations.last || NullMigration.new
         
     | 
| 
       1080 
1105 
     | 
    
         
             
                end
         
     | 
| 
       1081 
1106 
     | 
    
         | 
| 
       1082 
     | 
    
         
            -
                def parse_migration_filename(filename) # :nodoc:
         
     | 
| 
       1083 
     | 
    
         
            -
                  File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
         
     | 
| 
       1084 
     | 
    
         
            -
                end
         
     | 
| 
       1085 
     | 
    
         
            -
             
     | 
| 
       1086 
1107 
     | 
    
         
             
                def migrations
         
     | 
| 
       1087 
1108 
     | 
    
         
             
                  migrations = migration_files.map do |file|
         
     | 
| 
       1088 
1109 
     | 
    
         
             
                    version, name, scope = parse_migration_filename(file)
         
     | 
| 
         @@ -1097,12 +1118,12 @@ module ActiveRecord 
     | 
|
| 
       1097 
1118 
     | 
    
         
             
                end
         
     | 
| 
       1098 
1119 
     | 
    
         | 
| 
       1099 
1120 
     | 
    
         
             
                def migrations_status
         
     | 
| 
       1100 
     | 
    
         
            -
                  db_list =  
     | 
| 
      
 1121 
     | 
    
         
            +
                  db_list = schema_migration.normalized_versions
         
     | 
| 
       1101 
1122 
     | 
    
         | 
| 
       1102 
1123 
     | 
    
         
             
                  file_list = migration_files.map do |file|
         
     | 
| 
       1103 
1124 
     | 
    
         
             
                    version, name, scope = parse_migration_filename(file)
         
     | 
| 
       1104 
1125 
     | 
    
         
             
                    raise IllegalMigrationNameError.new(file) unless version
         
     | 
| 
       1105 
     | 
    
         
            -
                    version =  
     | 
| 
      
 1126 
     | 
    
         
            +
                    version = schema_migration.normalize_migration_number(version)
         
     | 
| 
       1106 
1127 
     | 
    
         
             
                    status = db_list.delete(version) ? "up" : "down"
         
     | 
| 
       1107 
1128 
     | 
    
         
             
                    [status, version, (name + scope).humanize]
         
     | 
| 
       1108 
1129 
     | 
    
         
             
                  end.compact
         
     | 
| 
         @@ -1114,11 +1135,6 @@ module ActiveRecord 
     | 
|
| 
       1114 
1135 
     | 
    
         
             
                  (db_list + file_list).sort_by { |_, version, _| version }
         
     | 
| 
       1115 
1136 
     | 
    
         
             
                end
         
     | 
| 
       1116 
1137 
     | 
    
         | 
| 
       1117 
     | 
    
         
            -
                def migration_files
         
     | 
| 
       1118 
     | 
    
         
            -
                  paths = Array(migrations_paths)
         
     | 
| 
       1119 
     | 
    
         
            -
                  Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
         
     | 
| 
       1120 
     | 
    
         
            -
                end
         
     | 
| 
       1121 
     | 
    
         
            -
             
     | 
| 
       1122 
1138 
     | 
    
         
             
                def current_environment
         
     | 
| 
       1123 
1139 
     | 
    
         
             
                  ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
         
     | 
| 
       1124 
1140 
     | 
    
         
             
                end
         
     | 
| 
         @@ -1137,8 +1153,17 @@ module ActiveRecord 
     | 
|
| 
       1137 
1153 
     | 
    
         
             
                end
         
     | 
| 
       1138 
1154 
     | 
    
         | 
| 
       1139 
1155 
     | 
    
         
             
                private
         
     | 
| 
      
 1156 
     | 
    
         
            +
                  def migration_files
         
     | 
| 
      
 1157 
     | 
    
         
            +
                    paths = Array(migrations_paths)
         
     | 
| 
      
 1158 
     | 
    
         
            +
                    Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
         
     | 
| 
      
 1159 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1160 
     | 
    
         
            +
             
     | 
| 
      
 1161 
     | 
    
         
            +
                  def parse_migration_filename(filename)
         
     | 
| 
      
 1162 
     | 
    
         
            +
                    File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
         
     | 
| 
      
 1163 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1164 
     | 
    
         
            +
             
     | 
| 
       1140 
1165 
     | 
    
         
             
                  def move(direction, steps)
         
     | 
| 
       1141 
     | 
    
         
            -
                    migrator = Migrator.new(direction, migrations)
         
     | 
| 
      
 1166 
     | 
    
         
            +
                    migrator = Migrator.new(direction, migrations, schema_migration)
         
     | 
| 
       1142 
1167 
     | 
    
         | 
| 
       1143 
1168 
     | 
    
         
             
                    if current_version != 0 && !migrator.current_migration
         
     | 
| 
       1144 
1169 
     | 
    
         
             
                      raise UnknownMigrationVersionError.new(current_version)
         
     | 
| 
         @@ -1161,30 +1186,24 @@ module ActiveRecord 
     | 
|
| 
       1161 
1186 
     | 
    
         
             
                class << self
         
     | 
| 
       1162 
1187 
     | 
    
         
             
                  attr_accessor :migrations_paths
         
     | 
| 
       1163 
1188 
     | 
    
         | 
| 
       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 
1189 
     | 
    
         
             
                  # For cases where a table doesn't exist like loading from schema cache
         
     | 
| 
       1172 
1190 
     | 
    
         
             
                  def current_version
         
     | 
| 
       1173 
     | 
    
         
            -
                    MigrationContext.new(migrations_paths).current_version
         
     | 
| 
      
 1191 
     | 
    
         
            +
                    MigrationContext.new(migrations_paths, SchemaMigration).current_version
         
     | 
| 
       1174 
1192 
     | 
    
         
             
                  end
         
     | 
| 
       1175 
1193 
     | 
    
         
             
                end
         
     | 
| 
       1176 
1194 
     | 
    
         | 
| 
       1177 
1195 
     | 
    
         
             
                self.migrations_paths = ["db/migrate"]
         
     | 
| 
       1178 
1196 
     | 
    
         | 
| 
       1179 
     | 
    
         
            -
                def initialize(direction, migrations, target_version = nil)
         
     | 
| 
      
 1197 
     | 
    
         
            +
                def initialize(direction, migrations, schema_migration, target_version = nil)
         
     | 
| 
       1180 
1198 
     | 
    
         
             
                  @direction         = direction
         
     | 
| 
       1181 
1199 
     | 
    
         
             
                  @target_version    = target_version
         
     | 
| 
       1182 
1200 
     | 
    
         
             
                  @migrated_versions = nil
         
     | 
| 
       1183 
1201 
     | 
    
         
             
                  @migrations        = migrations
         
     | 
| 
      
 1202 
     | 
    
         
            +
                  @schema_migration  = schema_migration
         
     | 
| 
       1184 
1203 
     | 
    
         | 
| 
       1185 
1204 
     | 
    
         
             
                  validate(@migrations)
         
     | 
| 
       1186 
1205 
     | 
    
         | 
| 
       1187 
     | 
    
         
            -
                   
     | 
| 
      
 1206 
     | 
    
         
            +
                  @schema_migration.create_table
         
     | 
| 
       1188 
1207 
     | 
    
         
             
                  ActiveRecord::InternalMetadata.create_table
         
     | 
| 
       1189 
1208 
     | 
    
         
             
                end
         
     | 
| 
       1190 
1209 
     | 
    
         | 
| 
         @@ -1238,7 +1257,7 @@ module ActiveRecord 
     | 
|
| 
       1238 
1257 
     | 
    
         
             
                end
         
     | 
| 
       1239 
1258 
     | 
    
         | 
| 
       1240 
1259 
     | 
    
         
             
                def load_migrated
         
     | 
| 
       1241 
     | 
    
         
            -
                  @migrated_versions = Set.new( 
     | 
| 
      
 1260 
     | 
    
         
            +
                  @migrated_versions = Set.new(@schema_migration.all_versions.map(&:to_i))
         
     | 
| 
       1242 
1261 
     | 
    
         
             
                end
         
     | 
| 
       1243 
1262 
     | 
    
         | 
| 
       1244 
1263 
     | 
    
         
             
                private
         
     | 
| 
         @@ -1293,7 +1312,7 @@ module ActiveRecord 
     | 
|
| 
       1293 
1312 
     | 
    
         
             
                      record_version_state_after_migrating(migration.version)
         
     | 
| 
       1294 
1313 
     | 
    
         
             
                    end
         
     | 
| 
       1295 
1314 
     | 
    
         
             
                  rescue => e
         
     | 
| 
       1296 
     | 
    
         
            -
                    msg = "An error has occurred, " 
     | 
| 
      
 1315 
     | 
    
         
            +
                    msg = +"An error has occurred, "
         
     | 
| 
       1297 
1316 
     | 
    
         
             
                    msg << "this and " if use_transaction?(migration)
         
     | 
| 
       1298 
1317 
     | 
    
         
             
                    msg << "all later migrations canceled:\n\n#{e}"
         
     | 
| 
       1299 
1318 
     | 
    
         
             
                    raise StandardError, msg, e.backtrace
         
     | 
| 
         @@ -1322,10 +1341,10 @@ module ActiveRecord 
     | 
|
| 
       1322 
1341 
     | 
    
         
             
                  def record_version_state_after_migrating(version)
         
     | 
| 
       1323 
1342 
     | 
    
         
             
                    if down?
         
     | 
| 
       1324 
1343 
     | 
    
         
             
                      migrated.delete(version)
         
     | 
| 
       1325 
     | 
    
         
            -
                       
     | 
| 
      
 1344 
     | 
    
         
            +
                      @schema_migration.delete_by(version: version.to_s)
         
     | 
| 
       1326 
1345 
     | 
    
         
             
                    else
         
     | 
| 
       1327 
1346 
     | 
    
         
             
                      migrated << version
         
     | 
| 
       1328 
     | 
    
         
            -
                       
     | 
| 
      
 1347 
     | 
    
         
            +
                      @schema_migration.create!(version: version.to_s)
         
     | 
| 
       1329 
1348 
     | 
    
         
             
                    end
         
     | 
| 
       1330 
1349 
     | 
    
         
             
                  end
         
     | 
| 
       1331 
1350 
     | 
    
         | 
| 
         @@ -1351,7 +1370,7 @@ module ActiveRecord 
     | 
|
| 
       1351 
1370 
     | 
    
         
             
                  end
         
     | 
| 
       1352 
1371 
     | 
    
         | 
| 
       1353 
1372 
     | 
    
         
             
                  def use_advisory_lock?
         
     | 
| 
       1354 
     | 
    
         
            -
                    Base.connection. 
     | 
| 
      
 1373 
     | 
    
         
            +
                    Base.connection.advisory_locks_enabled?
         
     | 
| 
       1355 
1374 
     | 
    
         
             
                  end
         
     | 
| 
       1356 
1375 
     | 
    
         | 
| 
       1357 
1376 
     | 
    
         
             
                  def with_advisory_lock
         
     |