activerecord 5.1.5 → 5.2.1
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 +450 -699
 - data/MIT-LICENSE +1 -1
 - data/README.rdoc +5 -5
 - data/examples/performance.rb +2 -0
 - data/examples/simple.rb +2 -0
 - data/lib/active_record/aggregations.rb +6 -5
 - data/lib/active_record/association_relation.rb +4 -2
 - data/lib/active_record/associations/alias_tracker.rb +19 -27
 - data/lib/active_record/associations/association.rb +33 -37
 - data/lib/active_record/associations/association_scope.rb +38 -50
 - data/lib/active_record/associations/belongs_to_association.rb +28 -9
 - data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
 - data/lib/active_record/associations/builder/association.rb +4 -7
 - data/lib/active_record/associations/builder/belongs_to.rb +14 -5
 - data/lib/active_record/associations/builder/collection_association.rb +1 -1
 - data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
 - data/lib/active_record/associations/builder/has_many.rb +2 -0
 - data/lib/active_record/associations/builder/has_one.rb +2 -0
 - data/lib/active_record/associations/builder/singular_association.rb +2 -0
 - data/lib/active_record/associations/collection_association.rb +52 -41
 - data/lib/active_record/associations/collection_proxy.rb +12 -15
 - data/lib/active_record/associations/foreign_association.rb +2 -0
 - data/lib/active_record/associations/has_many_association.rb +3 -1
 - data/lib/active_record/associations/has_many_through_association.rb +8 -19
 - data/lib/active_record/associations/has_one_association.rb +12 -1
 - data/lib/active_record/associations/has_one_through_association.rb +13 -8
 - data/lib/active_record/associations/join_dependency/join_association.rb +22 -67
 - data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
 - data/lib/active_record/associations/join_dependency/join_part.rb +9 -9
 - data/lib/active_record/associations/join_dependency.rb +48 -93
 - data/lib/active_record/associations/preloader/association.rb +45 -61
 - data/lib/active_record/associations/preloader/through_association.rb +71 -79
 - data/lib/active_record/associations/preloader.rb +17 -37
 - data/lib/active_record/associations/singular_association.rb +14 -16
 - data/lib/active_record/associations/through_association.rb +26 -11
 - data/lib/active_record/associations.rb +40 -63
 - data/lib/active_record/attribute_assignment.rb +2 -5
 - data/lib/active_record/attribute_decorators.rb +3 -2
 - data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
 - data/lib/active_record/attribute_methods/dirty.rb +25 -214
 - data/lib/active_record/attribute_methods/primary_key.rb +7 -6
 - data/lib/active_record/attribute_methods/query.rb +2 -0
 - data/lib/active_record/attribute_methods/read.rb +9 -3
 - data/lib/active_record/attribute_methods/serialization.rb +23 -0
 - data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
 - data/lib/active_record/attribute_methods/write.rb +21 -9
 - data/lib/active_record/attribute_methods.rb +65 -24
 - data/lib/active_record/attributes.rb +7 -6
 - data/lib/active_record/autosave_association.rb +16 -14
 - data/lib/active_record/base.rb +2 -0
 - data/lib/active_record/callbacks.rb +12 -6
 - data/lib/active_record/coders/json.rb +2 -0
 - data/lib/active_record/coders/yaml_column.rb +2 -0
 - data/lib/active_record/collection_cache_key.rb +11 -7
 - data/lib/active_record/connection_adapters/abstract/connection_pool.rb +110 -35
 - data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -0
 - data/lib/active_record/connection_adapters/abstract/database_statements.rb +157 -29
 - data/lib/active_record/connection_adapters/abstract/query_cache.rb +7 -2
 - data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -32
 - data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
 - data/lib/active_record/connection_adapters/abstract/schema_creation.rb +14 -5
 - data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +64 -6
 - data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
 - data/lib/active_record/connection_adapters/abstract/schema_statements.rb +149 -78
 - data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -21
 - data/lib/active_record/connection_adapters/abstract_adapter.rb +81 -96
 - data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +92 -165
 - data/lib/active_record/connection_adapters/column.rb +3 -1
 - data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
 - data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -0
 - data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
 - data/lib/active_record/connection_adapters/mysql/database_statements.rb +47 -2
 - data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
 - data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
 - data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
 - data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -10
 - data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -30
 - data/lib/active_record/connection_adapters/mysql/schema_statements.rb +106 -1
 - data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
 - data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
 - data/lib/active_record/connection_adapters/postgresql/column.rb +2 -0
 - data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -0
 - data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/array.rb +6 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
 - data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -1
 - data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
 - data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/range.rb +8 -2
 - data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
 - data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
 - data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
 - data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
 - data/lib/active_record/connection_adapters/postgresql/oid.rb +3 -1
 - data/lib/active_record/connection_adapters/postgresql/quoting.rb +18 -0
 - data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
 - data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +14 -0
 - data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
 - data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
 - data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +248 -112
 - data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
 - data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -0
 - data/lib/active_record/connection_adapters/postgresql_adapter.rb +57 -73
 - data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
 - data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
 - data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
 - data/lib/active_record/connection_adapters/sqlite3/quoting.rb +20 -1
 - data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
 - data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
 - data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
 - data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +75 -1
 - data/lib/active_record/connection_adapters/sqlite3_adapter.rb +79 -92
 - data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
 - data/lib/active_record/connection_handling.rb +4 -2
 - data/lib/active_record/core.rb +39 -60
 - data/lib/active_record/counter_cache.rb +20 -15
 - data/lib/active_record/define_callbacks.rb +5 -3
 - data/lib/active_record/dynamic_matchers.rb +9 -9
 - data/lib/active_record/enum.rb +17 -13
 - data/lib/active_record/errors.rb +42 -3
 - data/lib/active_record/explain.rb +3 -1
 - data/lib/active_record/explain_registry.rb +2 -0
 - data/lib/active_record/explain_subscriber.rb +2 -0
 - data/lib/active_record/fixture_set/file.rb +2 -0
 - data/lib/active_record/fixtures.rb +67 -60
 - data/lib/active_record/gem_version.rb +4 -2
 - data/lib/active_record/inheritance.rb +49 -19
 - data/lib/active_record/integration.rb +58 -19
 - data/lib/active_record/internal_metadata.rb +2 -0
 - data/lib/active_record/legacy_yaml_adapter.rb +3 -1
 - data/lib/active_record/locking/optimistic.rb +30 -42
 - data/lib/active_record/locking/pessimistic.rb +9 -6
 - data/lib/active_record/log_subscriber.rb +43 -0
 - data/lib/active_record/migration/command_recorder.rb +11 -9
 - data/lib/active_record/migration/compatibility.rb +40 -2
 - data/lib/active_record/migration/join_table.rb +2 -0
 - data/lib/active_record/migration.rb +189 -139
 - data/lib/active_record/model_schema.rb +19 -24
 - data/lib/active_record/nested_attributes.rb +18 -6
 - data/lib/active_record/no_touching.rb +3 -1
 - data/lib/active_record/null_relation.rb +2 -0
 - data/lib/active_record/persistence.rb +196 -48
 - data/lib/active_record/query_cache.rb +12 -14
 - data/lib/active_record/querying.rb +3 -1
 - data/lib/active_record/railtie.rb +61 -3
 - data/lib/active_record/railties/console_sandbox.rb +2 -0
 - data/lib/active_record/railties/controller_runtime.rb +2 -0
 - data/lib/active_record/railties/databases.rake +46 -36
 - data/lib/active_record/readonly_attributes.rb +3 -2
 - data/lib/active_record/reflection.rb +110 -192
 - data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
 - data/lib/active_record/relation/batches.rb +20 -5
 - data/lib/active_record/relation/calculations.rb +31 -9
 - data/lib/active_record/relation/delegation.rb +15 -27
 - data/lib/active_record/relation/finder_methods.rb +71 -76
 - data/lib/active_record/relation/from_clause.rb +2 -8
 - data/lib/active_record/relation/merger.rb +47 -20
 - data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
 - data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
 - data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
 - data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
 - data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
 - data/lib/active_record/relation/predicate_builder/range_handler.rb +26 -9
 - data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
 - data/lib/active_record/relation/predicate_builder.rb +55 -79
 - data/lib/active_record/relation/query_attribute.rb +26 -2
 - data/lib/active_record/relation/query_methods.rb +95 -91
 - data/lib/active_record/relation/record_fetch_warning.rb +2 -0
 - data/lib/active_record/relation/spawn_methods.rb +3 -1
 - data/lib/active_record/relation/where_clause.rb +65 -68
 - data/lib/active_record/relation/where_clause_factory.rb +5 -48
 - data/lib/active_record/relation.rb +106 -219
 - data/lib/active_record/result.rb +2 -0
 - data/lib/active_record/runtime_registry.rb +2 -0
 - data/lib/active_record/sanitization.rb +129 -121
 - data/lib/active_record/schema.rb +4 -2
 - data/lib/active_record/schema_dumper.rb +36 -26
 - data/lib/active_record/schema_migration.rb +2 -0
 - data/lib/active_record/scoping/default.rb +6 -7
 - data/lib/active_record/scoping/named.rb +21 -7
 - data/lib/active_record/scoping.rb +9 -8
 - data/lib/active_record/secure_token.rb +2 -0
 - data/lib/active_record/serialization.rb +2 -0
 - data/lib/active_record/statement_cache.rb +22 -12
 - data/lib/active_record/store.rb +3 -1
 - data/lib/active_record/suppressor.rb +2 -0
 - data/lib/active_record/table_metadata.rb +12 -3
 - data/lib/active_record/tasks/database_tasks.rb +25 -14
 - data/lib/active_record/tasks/mysql_database_tasks.rb +9 -48
 - data/lib/active_record/tasks/postgresql_database_tasks.rb +10 -2
 - data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
 - data/lib/active_record/timestamp.rb +13 -6
 - data/lib/active_record/touch_later.rb +2 -0
 - data/lib/active_record/transactions.rb +32 -27
 - data/lib/active_record/translation.rb +2 -0
 - data/lib/active_record/type/adapter_specific_registry.rb +2 -0
 - data/lib/active_record/type/date.rb +2 -0
 - data/lib/active_record/type/date_time.rb +2 -0
 - data/lib/active_record/type/decimal_without_scale.rb +2 -0
 - data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
 - data/lib/active_record/type/internal/timezone.rb +2 -0
 - data/lib/active_record/type/json.rb +30 -0
 - data/lib/active_record/type/serialized.rb +6 -0
 - data/lib/active_record/type/text.rb +2 -0
 - data/lib/active_record/type/time.rb +2 -0
 - data/lib/active_record/type/type_map.rb +2 -0
 - data/lib/active_record/type/unsigned_integer.rb +2 -0
 - data/lib/active_record/type.rb +4 -1
 - data/lib/active_record/type_caster/connection.rb +2 -0
 - data/lib/active_record/type_caster/map.rb +3 -1
 - data/lib/active_record/type_caster.rb +2 -0
 - data/lib/active_record/validations/absence.rb +2 -0
 - data/lib/active_record/validations/associated.rb +2 -0
 - data/lib/active_record/validations/length.rb +2 -0
 - data/lib/active_record/validations/presence.rb +2 -0
 - data/lib/active_record/validations/uniqueness.rb +36 -6
 - data/lib/active_record/validations.rb +2 -0
 - data/lib/active_record/version.rb +2 -0
 - data/lib/active_record.rb +11 -4
 - data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
 - data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
 - data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
 - data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
 - data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
 - data/lib/rails/generators/active_record/migration.rb +2 -0
 - data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
 - data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
 - data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
 - data/lib/rails/generators/active_record.rb +3 -1
 - metadata +23 -36
 - data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
 - data/lib/active_record/associations/preloader/collection_association.rb +0 -17
 - data/lib/active_record/associations/preloader/has_many.rb +0 -15
 - data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
 - data/lib/active_record/associations/preloader/has_one.rb +0 -15
 - data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
 - data/lib/active_record/associations/preloader/singular_association.rb +0 -18
 - data/lib/active_record/attribute/user_provided_default.rb +0 -30
 - data/lib/active_record/attribute.rb +0 -240
 - data/lib/active_record/attribute_mutation_tracker.rb +0 -114
 - data/lib/active_record/attribute_set/builder.rb +0 -124
 - data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
 - data/lib/active_record/attribute_set.rb +0 -113
 - data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
 - data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
 - data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
 - data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
 - data/lib/active_record/type/internal/abstract_json.rb +0 -37
 
| 
         @@ -1,4 +1,6 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "active_model/attribute/user_provided_default"
         
     | 
| 
       2 
4 
     | 
    
         | 
| 
       3 
5 
     | 
    
         
             
            module ActiveRecord
         
     | 
| 
       4 
6 
     | 
    
         
             
              # See ActiveRecord::Attributes::ClassMethods for documentation
         
     | 
| 
         @@ -6,8 +8,7 @@ module ActiveRecord 
     | 
|
| 
       6 
8 
     | 
    
         
             
                extend ActiveSupport::Concern
         
     | 
| 
       7 
9 
     | 
    
         | 
| 
       8 
10 
     | 
    
         
             
                included do
         
     | 
| 
       9 
     | 
    
         
            -
                  class_attribute :attributes_to_define_after_schema_loads, instance_accessor: false # :internal:
         
     | 
| 
       10 
     | 
    
         
            -
                  self.attributes_to_define_after_schema_loads = {}
         
     | 
| 
      
 11 
     | 
    
         
            +
                  class_attribute :attributes_to_define_after_schema_loads, instance_accessor: false, default: {} # :internal:
         
     | 
| 
       11 
12 
     | 
    
         
             
                end
         
     | 
| 
       12 
13 
     | 
    
         | 
| 
       13 
14 
     | 
    
         
             
                module ClassMethods
         
     | 
| 
         @@ -56,7 +57,7 @@ module ActiveRecord 
     | 
|
| 
       56 
57 
     | 
    
         
             
                  #   store_listing = StoreListing.new(price_in_cents: '10.1')
         
     | 
| 
       57 
58 
     | 
    
         
             
                  #
         
     | 
| 
       58 
59 
     | 
    
         
             
                  #   # before
         
     | 
| 
       59 
     | 
    
         
            -
                  #   store_listing.price_in_cents # => BigDecimal 
     | 
| 
      
 60 
     | 
    
         
            +
                  #   store_listing.price_in_cents # => BigDecimal(10.1)
         
     | 
| 
       60 
61 
     | 
    
         
             
                  #
         
     | 
| 
       61 
62 
     | 
    
         
             
                  #   class StoreListing < ActiveRecord::Base
         
     | 
| 
       62 
63 
     | 
    
         
             
                  #     attribute :price_in_cents, :integer
         
     | 
| 
         @@ -249,14 +250,14 @@ module ActiveRecord 
     | 
|
| 
       249 
250 
     | 
    
         
             
                      if value == NO_DEFAULT_PROVIDED
         
     | 
| 
       250 
251 
     | 
    
         
             
                        default_attribute = _default_attributes[name].with_type(type)
         
     | 
| 
       251 
252 
     | 
    
         
             
                      elsif from_user
         
     | 
| 
       252 
     | 
    
         
            -
                        default_attribute = Attribute::UserProvidedDefault.new(
         
     | 
| 
      
 253 
     | 
    
         
            +
                        default_attribute = ActiveModel::Attribute::UserProvidedDefault.new(
         
     | 
| 
       253 
254 
     | 
    
         
             
                          name,
         
     | 
| 
       254 
255 
     | 
    
         
             
                          value,
         
     | 
| 
       255 
256 
     | 
    
         
             
                          type,
         
     | 
| 
       256 
257 
     | 
    
         
             
                          _default_attributes.fetch(name.to_s) { nil },
         
     | 
| 
       257 
258 
     | 
    
         
             
                        )
         
     | 
| 
       258 
259 
     | 
    
         
             
                      else
         
     | 
| 
       259 
     | 
    
         
            -
                        default_attribute = Attribute.from_database(name, value, type)
         
     | 
| 
      
 260 
     | 
    
         
            +
                        default_attribute = ActiveModel::Attribute.from_database(name, value, type)
         
     | 
| 
       260 
261 
     | 
    
         
             
                      end
         
     | 
| 
       261 
262 
     | 
    
         
             
                      _default_attributes[name] = default_attribute
         
     | 
| 
       262 
263 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -1,3 +1,5 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       1 
3 
     | 
    
         
             
            module ActiveRecord
         
     | 
| 
       2 
4 
     | 
    
         
             
              # = Active Record Autosave Association
         
     | 
| 
       3 
5 
     | 
    
         
             
              #
         
     | 
| 
         @@ -140,8 +142,7 @@ module ActiveRecord 
     | 
|
| 
       140 
142 
     | 
    
         | 
| 
       141 
143 
     | 
    
         
             
                included do
         
     | 
| 
       142 
144 
     | 
    
         
             
                  Associations::Builder::Association.extensions << AssociationBuilderExtension
         
     | 
| 
       143 
     | 
    
         
            -
                  mattr_accessor :index_nested_attribute_errors, instance_writer: false
         
     | 
| 
       144 
     | 
    
         
            -
                  self.index_nested_attribute_errors = false
         
     | 
| 
      
 145 
     | 
    
         
            +
                  mattr_accessor :index_nested_attribute_errors, instance_writer: false, default: false
         
     | 
| 
       145 
146 
     | 
    
         
             
                end
         
     | 
| 
       146 
147 
     | 
    
         | 
| 
       147 
148 
     | 
    
         
             
                module ClassMethods # :nodoc:
         
     | 
| 
         @@ -216,13 +217,7 @@ module ActiveRecord 
     | 
|
| 
       216 
217 
     | 
    
         
             
                          method = :validate_single_association
         
     | 
| 
       217 
218 
     | 
    
         
             
                        end
         
     | 
| 
       218 
219 
     | 
    
         | 
| 
       219 
     | 
    
         
            -
                        define_non_cyclic_method(validation_method)  
     | 
| 
       220 
     | 
    
         
            -
                          send(method, reflection)
         
     | 
| 
       221 
     | 
    
         
            -
                          # TODO: remove the following line as soon as the return value of
         
     | 
| 
       222 
     | 
    
         
            -
                          # callbacks is ignored, that is, returning `false` does not
         
     | 
| 
       223 
     | 
    
         
            -
                          # display a deprecation warning or halts the callback chain.
         
     | 
| 
       224 
     | 
    
         
            -
                          true
         
     | 
| 
       225 
     | 
    
         
            -
                        end
         
     | 
| 
      
 220 
     | 
    
         
            +
                        define_non_cyclic_method(validation_method) { send(method, reflection) }
         
     | 
| 
       226 
221 
     | 
    
         
             
                        validate validation_method
         
     | 
| 
       227 
222 
     | 
    
         
             
                        after_validation :_ensure_no_duplicate_errors
         
     | 
| 
       228 
223 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -369,7 +364,6 @@ module ActiveRecord 
     | 
|
| 
       369 
364 
     | 
    
         
             
                  # association whether or not the parent was a new record before saving.
         
     | 
| 
       370 
365 
     | 
    
         
             
                  def before_save_collection_association
         
     | 
| 
       371 
366 
     | 
    
         
             
                    @new_record_before_save = new_record?
         
     | 
| 
       372 
     | 
    
         
            -
                    true
         
     | 
| 
       373 
367 
     | 
    
         
             
                  end
         
     | 
| 
       374 
368 
     | 
    
         | 
| 
       375 
369 
     | 
    
         
             
                  def after_save_collection_association
         
     | 
| 
         @@ -389,7 +383,7 @@ module ActiveRecord 
     | 
|
| 
       389 
383 
     | 
    
         
             
                      autosave = reflection.options[:autosave]
         
     | 
| 
       390 
384 
     | 
    
         | 
| 
       391 
385 
     | 
    
         
             
                      # reconstruct the scope now that we know the owner's id
         
     | 
| 
       392 
     | 
    
         
            -
                      association.reset_scope 
     | 
| 
      
 386 
     | 
    
         
            +
                      association.reset_scope
         
     | 
| 
       393 
387 
     | 
    
         | 
| 
       394 
388 
     | 
    
         
             
                      if records = associated_records_to_validate_or_save(association, @new_record_before_save, autosave)
         
     | 
| 
       395 
389 
     | 
    
         
             
                        if autosave
         
     | 
| 
         @@ -398,7 +392,7 @@ module ActiveRecord 
     | 
|
| 
       398 
392 
     | 
    
         
             
                          records -= records_to_destroy
         
     | 
| 
       399 
393 
     | 
    
         
             
                        end
         
     | 
| 
       400 
394 
     | 
    
         | 
| 
       401 
     | 
    
         
            -
                        records. 
     | 
| 
      
 395 
     | 
    
         
            +
                        records.each_with_index do |record, index|
         
     | 
| 
       402 
396 
     | 
    
         
             
                          next if record.destroyed?
         
     | 
| 
       403 
397 
     | 
    
         | 
| 
       404 
398 
     | 
    
         
             
                          saved = true
         
     | 
| 
         @@ -406,8 +400,13 @@ module ActiveRecord 
     | 
|
| 
       406 
400 
     | 
    
         
             
                          if autosave != false && (@new_record_before_save || record.new_record?)
         
     | 
| 
       407 
401 
     | 
    
         
             
                            if autosave
         
     | 
| 
       408 
402 
     | 
    
         
             
                              saved = association.insert_record(record, false)
         
     | 
| 
       409 
     | 
    
         
            -
                             
     | 
| 
       410 
     | 
    
         
            -
                               
     | 
| 
      
 403 
     | 
    
         
            +
                            elsif !reflection.nested?
         
     | 
| 
      
 404 
     | 
    
         
            +
                              if reflection.validate?
         
     | 
| 
      
 405 
     | 
    
         
            +
                                valid = association_valid?(reflection, record, index)
         
     | 
| 
      
 406 
     | 
    
         
            +
                                saved = valid ? association.insert_record(record, false) : false
         
     | 
| 
      
 407 
     | 
    
         
            +
                              else
         
     | 
| 
      
 408 
     | 
    
         
            +
                                association.insert_record(record)
         
     | 
| 
      
 409 
     | 
    
         
            +
                              end
         
     | 
| 
       411 
410 
     | 
    
         
             
                            end
         
     | 
| 
       412 
411 
     | 
    
         
             
                          elsif autosave
         
     | 
| 
       413 
412 
     | 
    
         
             
                            saved = record.save(validate: false)
         
     | 
| 
         @@ -442,6 +441,9 @@ module ActiveRecord 
     | 
|
| 
       442 
441 
     | 
    
         
             
                        if (autosave && record.changed_for_autosave?) || new_record? || record_changed?(reflection, record, key)
         
     | 
| 
       443 
442 
     | 
    
         
             
                          unless reflection.through_reflection
         
     | 
| 
       444 
443 
     | 
    
         
             
                            record[reflection.foreign_key] = key
         
     | 
| 
      
 444 
     | 
    
         
            +
                            if inverse_reflection = reflection.inverse_of
         
     | 
| 
      
 445 
     | 
    
         
            +
                              record.association(inverse_reflection.name).loaded!
         
     | 
| 
      
 446 
     | 
    
         
            +
                            end
         
     | 
| 
       445 
447 
     | 
    
         
             
                          end
         
     | 
| 
       446 
448 
     | 
    
         | 
| 
       447 
449 
     | 
    
         
             
                          saved = record.save(validate: !autosave)
         
     | 
    
        data/lib/active_record/base.rb
    CHANGED
    
    
| 
         @@ -1,3 +1,5 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       1 
3 
     | 
    
         
             
            module ActiveRecord
         
     | 
| 
       2 
4 
     | 
    
         
             
              # = Active Record \Callbacks
         
     | 
| 
       3 
5 
     | 
    
         
             
              #
         
     | 
| 
         @@ -96,9 +98,9 @@ module ActiveRecord 
     | 
|
| 
       96 
98 
     | 
    
         
             
              # == Types of callbacks
         
     | 
| 
       97 
99 
     | 
    
         
             
              #
         
     | 
| 
       98 
100 
     | 
    
         
             
              # There are four types of callbacks accepted by the callback macros: Method references (symbol), callback objects,
         
     | 
| 
       99 
     | 
    
         
            -
              # inline methods (using a proc) 
     | 
| 
      
 101 
     | 
    
         
            +
              # inline methods (using a proc). Method references and callback objects
         
     | 
| 
       100 
102 
     | 
    
         
             
              # are the recommended approaches, inline methods using a proc are sometimes appropriate (such as for
         
     | 
| 
       101 
     | 
    
         
            -
              # creating mix-ins) 
     | 
| 
      
 103 
     | 
    
         
            +
              # creating mix-ins).
         
     | 
| 
       102 
104 
     | 
    
         
             
              #
         
     | 
| 
       103 
105 
     | 
    
         
             
              # The method reference callbacks work by specifying a protected or private method available in the object, like this:
         
     | 
| 
       104 
106 
     | 
    
         
             
              #
         
     | 
| 
         @@ -230,7 +232,7 @@ module ActiveRecord 
     | 
|
| 
       230 
232 
     | 
    
         
             
              #
         
     | 
| 
       231 
233 
     | 
    
         
             
              # For example:
         
     | 
| 
       232 
234 
     | 
    
         
             
              #
         
     | 
| 
       233 
     | 
    
         
            -
              #   class Topic
         
     | 
| 
      
 235 
     | 
    
         
            +
              #   class Topic < ActiveRecord::Base
         
     | 
| 
       234 
236 
     | 
    
         
             
              #     has_many :children
         
     | 
| 
       235 
237 
     | 
    
         
             
              #
         
     | 
| 
       236 
238 
     | 
    
         
             
              #     after_save :log_children
         
     | 
| 
         @@ -238,7 +240,7 @@ module ActiveRecord 
     | 
|
| 
       238 
240 
     | 
    
         
             
              #
         
     | 
| 
       239 
241 
     | 
    
         
             
              #     private
         
     | 
| 
       240 
242 
     | 
    
         
             
              #
         
     | 
| 
       241 
     | 
    
         
            -
              #     def  
     | 
| 
      
 243 
     | 
    
         
            +
              #     def log_children
         
     | 
| 
       242 
244 
     | 
    
         
             
              #       # Child processing
         
     | 
| 
       243 
245 
     | 
    
         
             
              #     end
         
     | 
| 
       244 
246 
     | 
    
         
             
              #
         
     | 
| 
         @@ -255,7 +257,7 @@ module ActiveRecord 
     | 
|
| 
       255 
257 
     | 
    
         
             
              #
         
     | 
| 
       256 
258 
     | 
    
         
             
              # For example:
         
     | 
| 
       257 
259 
     | 
    
         
             
              #
         
     | 
| 
       258 
     | 
    
         
            -
              #   class Topic
         
     | 
| 
      
 260 
     | 
    
         
            +
              #   class Topic < ActiveRecord::Base
         
     | 
| 
       259 
261 
     | 
    
         
             
              #     has_many :children
         
     | 
| 
       260 
262 
     | 
    
         
             
              #
         
     | 
| 
       261 
263 
     | 
    
         
             
              #     after_commit :log_children
         
     | 
| 
         @@ -263,7 +265,7 @@ module ActiveRecord 
     | 
|
| 
       263 
265 
     | 
    
         
             
              #
         
     | 
| 
       264 
266 
     | 
    
         
             
              #     private
         
     | 
| 
       265 
267 
     | 
    
         
             
              #
         
     | 
| 
       266 
     | 
    
         
            -
              #     def  
     | 
| 
      
 268 
     | 
    
         
            +
              #     def log_children
         
     | 
| 
       267 
269 
     | 
    
         
             
              #       # Child processing
         
     | 
| 
       268 
270 
     | 
    
         
             
              #     end
         
     | 
| 
       269 
271 
     | 
    
         
             
              #
         
     | 
| 
         @@ -330,6 +332,10 @@ module ActiveRecord 
     | 
|
| 
       330 
332 
     | 
    
         
             
                  _run_touch_callbacks { super }
         
     | 
| 
       331 
333 
     | 
    
         
             
                end
         
     | 
| 
       332 
334 
     | 
    
         | 
| 
      
 335 
     | 
    
         
            +
                def increment!(*, touch: nil) # :nodoc:
         
     | 
| 
      
 336 
     | 
    
         
            +
                  touch ? _run_touch_callbacks { super } : super
         
     | 
| 
      
 337 
     | 
    
         
            +
                end
         
     | 
| 
      
 338 
     | 
    
         
            +
             
     | 
| 
       333 
339 
     | 
    
         
             
              private
         
     | 
| 
       334 
340 
     | 
    
         | 
| 
       335 
341 
     | 
    
         
             
                def create_or_update(*)
         
     | 
| 
         @@ -1,7 +1,9 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       1 
3 
     | 
    
         
             
            module ActiveRecord
         
     | 
| 
       2 
4 
     | 
    
         
             
              module CollectionCacheKey
         
     | 
| 
       3 
5 
     | 
    
         
             
                def collection_cache_key(collection = all, timestamp_column = :updated_at) # :nodoc:
         
     | 
| 
       4 
     | 
    
         
            -
                  query_signature = Digest 
     | 
| 
      
 6 
     | 
    
         
            +
                  query_signature = ActiveSupport::Digest.hexdigest(collection.to_sql)
         
     | 
| 
       5 
7 
     | 
    
         
             
                  key = "#{collection.model_name.cache_key}/query-#{query_signature}"
         
     | 
| 
       6 
8 
     | 
    
         | 
| 
       7 
9 
     | 
    
         
             
                  if collection.loaded? || collection.distinct_value
         
     | 
| 
         @@ -10,24 +12,26 @@ module ActiveRecord 
     | 
|
| 
       10 
12 
     | 
    
         
             
                      timestamp = collection.max_by(×tamp_column)._read_attribute(timestamp_column)
         
     | 
| 
       11 
13 
     | 
    
         
             
                    end
         
     | 
| 
       12 
14 
     | 
    
         
             
                  else
         
     | 
| 
       13 
     | 
    
         
            -
                     
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
      
 15 
     | 
    
         
            +
                    if collection.eager_loading?
         
     | 
| 
      
 16 
     | 
    
         
            +
                      collection = collection.send(:apply_join_dependency)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    end
         
     | 
| 
      
 18 
     | 
    
         
            +
                    column_type = type_for_attribute(timestamp_column)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    column = connection.column_name_from_arel_node(collection.arel_attribute(timestamp_column))
         
     | 
| 
       15 
20 
     | 
    
         
             
                    select_values = "COUNT(*) AS #{connection.quote_column_name("size")}, MAX(%s) AS timestamp"
         
     | 
| 
       16 
21 
     | 
    
         | 
| 
       17 
22 
     | 
    
         
             
                    if collection.has_limit_or_offset?
         
     | 
| 
       18 
     | 
    
         
            -
                      query = collection. 
     | 
| 
       19 
     | 
    
         
            -
                      query.select_values = [column]
         
     | 
| 
      
 23 
     | 
    
         
            +
                      query = collection.select(column)
         
     | 
| 
       20 
24 
     | 
    
         
             
                      subquery_alias = "subquery_for_cache_key"
         
     | 
| 
       21 
25 
     | 
    
         
             
                      subquery_column = "#{subquery_alias}.#{timestamp_column}"
         
     | 
| 
       22 
26 
     | 
    
         
             
                      subquery = query.arel.as(subquery_alias)
         
     | 
| 
       23 
     | 
    
         
            -
                      arel = Arel::SelectManager.new( 
     | 
| 
      
 27 
     | 
    
         
            +
                      arel = Arel::SelectManager.new(subquery).project(select_values % subquery_column)
         
     | 
| 
       24 
28 
     | 
    
         
             
                    else
         
     | 
| 
       25 
29 
     | 
    
         
             
                      query = collection.unscope(:order)
         
     | 
| 
       26 
30 
     | 
    
         
             
                      query.select_values = [select_values % column]
         
     | 
| 
       27 
31 
     | 
    
         
             
                      arel = query.arel
         
     | 
| 
       28 
32 
     | 
    
         
             
                    end
         
     | 
| 
       29 
33 
     | 
    
         | 
| 
       30 
     | 
    
         
            -
                    result = connection.select_one(arel, nil 
     | 
| 
      
 34 
     | 
    
         
            +
                    result = connection.select_one(arel, nil)
         
     | 
| 
       31 
35 
     | 
    
         | 
| 
       32 
36 
     | 
    
         
             
                    if result.blank?
         
     | 
| 
       33 
37 
     | 
    
         
             
                      size = 0
         
     | 
| 
         @@ -1,3 +1,5 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
       1 
3 
     | 
    
         
             
            require "thread"
         
     | 
| 
       2 
4 
     | 
    
         
             
            require "concurrent/map"
         
     | 
| 
       3 
5 
     | 
    
         
             
            require "monitor"
         
     | 
| 
         @@ -61,15 +63,13 @@ module ActiveRecord 
     | 
|
| 
       61 
63 
     | 
    
         
             
                # There are several connection-pooling-related options that you can add to
         
     | 
| 
       62 
64 
     | 
    
         
             
                # your database connection configuration:
         
     | 
| 
       63 
65 
     | 
    
         
             
                #
         
     | 
| 
       64 
     | 
    
         
            -
                # * +pool+: number  
     | 
| 
       65 
     | 
    
         
            -
                # * + 
     | 
| 
       66 
     | 
    
         
            -
                #    
     | 
| 
       67 
     | 
    
         
            -
                #  
     | 
| 
       68 
     | 
    
         
            -
                # 
     | 
| 
       69 
     | 
    
         
            -
                #    
     | 
| 
       70 
     | 
    
         
            -
                #    
     | 
| 
       71 
     | 
    
         
            -
                #   Regardless of this setting, the Reaper will be invoked before every
         
     | 
| 
       72 
     | 
    
         
            -
                #   blocking wait. (Default +nil+, which means don't schedule the Reaper).
         
     | 
| 
      
 66 
     | 
    
         
            +
                # * +pool+: maximum number of connections the pool may manage (default 5).
         
     | 
| 
      
 67 
     | 
    
         
            +
                # * +idle_timeout+: number of seconds that a connection will be kept
         
     | 
| 
      
 68 
     | 
    
         
            +
                #   unused in the pool before it is automatically disconnected (default
         
     | 
| 
      
 69 
     | 
    
         
            +
                #   300 seconds). Set this to zero to keep connections forever.
         
     | 
| 
      
 70 
     | 
    
         
            +
                # * +checkout_timeout+: number of seconds to wait for a connection to
         
     | 
| 
      
 71 
     | 
    
         
            +
                #   become available before giving up and raising a timeout error (default
         
     | 
| 
      
 72 
     | 
    
         
            +
                #   5 seconds).
         
     | 
| 
       73 
73 
     | 
    
         
             
                #
         
     | 
| 
       74 
74 
     | 
    
         
             
                #--
         
     | 
| 
       75 
75 
     | 
    
         
             
                # Synchronization policy:
         
     | 
| 
         @@ -80,11 +80,8 @@ module ActiveRecord 
     | 
|
| 
       80 
80 
     | 
    
         
             
                # * private methods that require being called in a +synchronize+ blocks
         
     | 
| 
       81 
81 
     | 
    
         
             
                #   are now explicitly documented
         
     | 
| 
       82 
82 
     | 
    
         
             
                class ConnectionPool
         
     | 
| 
       83 
     | 
    
         
            -
                  # Threadsafe, fair,  
     | 
| 
       84 
     | 
    
         
            -
                  # with which it shares a Monitor. 
     | 
| 
       85 
     | 
    
         
            -
                  #
         
     | 
| 
       86 
     | 
    
         
            -
                  # The Queue in stdlib's 'thread' could replace this class except
         
     | 
| 
       87 
     | 
    
         
            -
                  # stdlib's doesn't support waiting with a timeout.
         
     | 
| 
      
 83 
     | 
    
         
            +
                  # Threadsafe, fair, LIFO queue.  Meant to be used by ConnectionPool
         
     | 
| 
      
 84 
     | 
    
         
            +
                  # with which it shares a Monitor.
         
     | 
| 
       88 
85 
     | 
    
         
             
                  class Queue
         
     | 
| 
       89 
86 
     | 
    
         
             
                    def initialize(lock = Monitor.new)
         
     | 
| 
       90 
87 
     | 
    
         
             
                      @lock = lock
         
     | 
| 
         @@ -173,7 +170,7 @@ module ActiveRecord 
     | 
|
| 
       173 
170 
     | 
    
         | 
| 
       174 
171 
     | 
    
         
             
                      # Removes and returns the head of the queue if possible, or +nil+.
         
     | 
| 
       175 
172 
     | 
    
         
             
                      def remove
         
     | 
| 
       176 
     | 
    
         
            -
                        @queue. 
     | 
| 
      
 173 
     | 
    
         
            +
                        @queue.pop
         
     | 
| 
       177 
174 
     | 
    
         
             
                      end
         
     | 
| 
       178 
175 
     | 
    
         | 
| 
       179 
176 
     | 
    
         
             
                      # Remove and return the head the queue if the number of
         
     | 
| 
         @@ -268,7 +265,7 @@ module ActiveRecord 
     | 
|
| 
       268 
265 
     | 
    
         
             
                  # Connections must be leased while holding the main pool mutex. This is
         
     | 
| 
       269 
266 
     | 
    
         
             
                  # an internal subclass that also +.leases+ returned connections while
         
     | 
| 
       270 
267 
     | 
    
         
             
                  # still in queue's critical section (queue synchronizes with the same
         
     | 
| 
       271 
     | 
    
         
            -
                  #  
     | 
| 
      
 268 
     | 
    
         
            +
                  # <tt>@lock</tt> as the main pool) so that a returned connection is already
         
     | 
| 
       272 
269 
     | 
    
         
             
                  # leased and there is no need to re-enter synchronized block.
         
     | 
| 
       273 
270 
     | 
    
         
             
                  class ConnectionLeasingQueue < Queue # :nodoc:
         
     | 
| 
       274 
271 
     | 
    
         
             
                    include BiasableQueue
         
     | 
| 
         @@ -281,12 +278,12 @@ module ActiveRecord 
     | 
|
| 
       281 
278 
     | 
    
         
             
                      end
         
     | 
| 
       282 
279 
     | 
    
         
             
                  end
         
     | 
| 
       283 
280 
     | 
    
         | 
| 
       284 
     | 
    
         
            -
                  # Every +frequency+ seconds, the reaper will call +reap+  
     | 
| 
       285 
     | 
    
         
            -
                  # A reaper instantiated with a  
     | 
| 
       286 
     | 
    
         
            -
                  # connection pool.
         
     | 
| 
      
 281 
     | 
    
         
            +
                  # Every +frequency+ seconds, the reaper will call +reap+ and +flush+ on
         
     | 
| 
      
 282 
     | 
    
         
            +
                  # +pool+. A reaper instantiated with a zero frequency will never reap
         
     | 
| 
      
 283 
     | 
    
         
            +
                  # the connection pool.
         
     | 
| 
       287 
284 
     | 
    
         
             
                  #
         
     | 
| 
       288 
     | 
    
         
            -
                  # Configure the frequency by setting  
     | 
| 
       289 
     | 
    
         
            -
                  #  
     | 
| 
      
 285 
     | 
    
         
            +
                  # Configure the frequency by setting +reaping_frequency+ in your database
         
     | 
| 
      
 286 
     | 
    
         
            +
                  # yaml file (default 60 seconds).
         
     | 
| 
       290 
287 
     | 
    
         
             
                  class Reaper
         
     | 
| 
       291 
288 
     | 
    
         
             
                    attr_reader :pool, :frequency
         
     | 
| 
       292 
289 
     | 
    
         | 
| 
         @@ -296,11 +293,12 @@ module ActiveRecord 
     | 
|
| 
       296 
293 
     | 
    
         
             
                    end
         
     | 
| 
       297 
294 
     | 
    
         | 
| 
       298 
295 
     | 
    
         
             
                    def run
         
     | 
| 
       299 
     | 
    
         
            -
                      return unless frequency
         
     | 
| 
      
 296 
     | 
    
         
            +
                      return unless frequency && frequency > 0
         
     | 
| 
       300 
297 
     | 
    
         
             
                      Thread.new(frequency, pool) { |t, p|
         
     | 
| 
       301 
298 
     | 
    
         
             
                        loop do
         
     | 
| 
       302 
299 
     | 
    
         
             
                          sleep t
         
     | 
| 
       303 
300 
     | 
    
         
             
                          p.reap
         
     | 
| 
      
 301 
     | 
    
         
            +
                          p.flush
         
     | 
| 
       304 
302 
     | 
    
         
             
                        end
         
     | 
| 
       305 
303 
     | 
    
         
             
                      }
         
     | 
| 
       306 
304 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -324,8 +322,10 @@ module ActiveRecord 
     | 
|
| 
       324 
322 
     | 
    
         
             
                    @spec = spec
         
     | 
| 
       325 
323 
     | 
    
         | 
| 
       326 
324 
     | 
    
         
             
                    @checkout_timeout = (spec.config[:checkout_timeout] && spec.config[:checkout_timeout].to_f) || 5
         
     | 
| 
       327 
     | 
    
         
            -
                    @ 
     | 
| 
       328 
     | 
    
         
            -
             
     | 
| 
      
 325 
     | 
    
         
            +
                    if @idle_timeout = spec.config.fetch(:idle_timeout, 300)
         
     | 
| 
      
 326 
     | 
    
         
            +
                      @idle_timeout = @idle_timeout.to_f
         
     | 
| 
      
 327 
     | 
    
         
            +
                      @idle_timeout = nil if @idle_timeout <= 0
         
     | 
| 
      
 328 
     | 
    
         
            +
                    end
         
     | 
| 
       329 
329 
     | 
    
         | 
| 
       330 
330 
     | 
    
         
             
                    # default max pool size to 5
         
     | 
| 
       331 
331 
     | 
    
         
             
                    @size = (spec.config[:pool] && spec.config[:pool].to_i) || 5
         
     | 
| 
         @@ -338,7 +338,7 @@ module ActiveRecord 
     | 
|
| 
       338 
338 
     | 
    
         
             
                    # then that +thread+ does indeed own that +conn+. However, an absence of a such
         
     | 
| 
       339 
339 
     | 
    
         
             
                    # mapping does not mean that the +thread+ doesn't own the said connection. In
         
     | 
| 
       340 
340 
     | 
    
         
             
                    # that case +conn.owner+ attr should be consulted.
         
     | 
| 
       341 
     | 
    
         
            -
                    # Access and modification of  
     | 
| 
      
 341 
     | 
    
         
            +
                    # Access and modification of <tt>@thread_cached_conns</tt> does not require
         
     | 
| 
       342 
342 
     | 
    
         
             
                    # synchronization.
         
     | 
| 
       343 
343 
     | 
    
         
             
                    @thread_cached_conns = Concurrent::Map.new(initial_capacity: @size)
         
     | 
| 
       344 
344 
     | 
    
         | 
| 
         @@ -355,6 +355,12 @@ module ActiveRecord 
     | 
|
| 
       355 
355 
     | 
    
         
             
                    @available = ConnectionLeasingQueue.new self
         
     | 
| 
       356 
356 
     | 
    
         | 
| 
       357 
357 
     | 
    
         
             
                    @lock_thread = false
         
     | 
| 
      
 358 
     | 
    
         
            +
             
     | 
| 
      
 359 
     | 
    
         
            +
                    # +reaping_frequency+ is configurable mostly for historical reasons, but it could
         
     | 
| 
      
 360 
     | 
    
         
            +
                    # also be useful if someone wants a very low +idle_timeout+.
         
     | 
| 
      
 361 
     | 
    
         
            +
                    reaping_frequency = spec.config.fetch(:reaping_frequency, 60)
         
     | 
| 
      
 362 
     | 
    
         
            +
                    @reaper = Reaper.new(self, reaping_frequency && reaping_frequency.to_f)
         
     | 
| 
      
 363 
     | 
    
         
            +
                    @reaper.run
         
     | 
| 
       358 
364 
     | 
    
         
             
                  end
         
     | 
| 
       359 
365 
     | 
    
         | 
| 
       360 
366 
     | 
    
         
             
                  def lock_thread=(lock_thread)
         
     | 
| 
         @@ -447,6 +453,21 @@ module ActiveRecord 
     | 
|
| 
       447 
453 
     | 
    
         
             
                    disconnect(false)
         
     | 
| 
       448 
454 
     | 
    
         
             
                  end
         
     | 
| 
       449 
455 
     | 
    
         | 
| 
      
 456 
     | 
    
         
            +
                  # Discards all connections in the pool (even if they're currently
         
     | 
| 
      
 457 
     | 
    
         
            +
                  # leased!), along with the pool itself. Any further interaction with the
         
     | 
| 
      
 458 
     | 
    
         
            +
                  # pool (except #spec and #schema_cache) is undefined.
         
     | 
| 
      
 459 
     | 
    
         
            +
                  #
         
     | 
| 
      
 460 
     | 
    
         
            +
                  # See AbstractAdapter#discard!
         
     | 
| 
      
 461 
     | 
    
         
            +
                  def discard! # :nodoc:
         
     | 
| 
      
 462 
     | 
    
         
            +
                    synchronize do
         
     | 
| 
      
 463 
     | 
    
         
            +
                      return if @connections.nil? # already discarded
         
     | 
| 
      
 464 
     | 
    
         
            +
                      @connections.each do |conn|
         
     | 
| 
      
 465 
     | 
    
         
            +
                        conn.discard!
         
     | 
| 
      
 466 
     | 
    
         
            +
                      end
         
     | 
| 
      
 467 
     | 
    
         
            +
                      @connections = @available = @thread_cached_conns = nil
         
     | 
| 
      
 468 
     | 
    
         
            +
                    end
         
     | 
| 
      
 469 
     | 
    
         
            +
                  end
         
     | 
| 
      
 470 
     | 
    
         
            +
             
     | 
| 
       450 
471 
     | 
    
         
             
                  # Clears the cache which maps classes and re-connects connections that
         
     | 
| 
       451 
472 
     | 
    
         
             
                  # require reloading.
         
     | 
| 
       452 
473 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -572,6 +593,35 @@ module ActiveRecord 
     | 
|
| 
       572 
593 
     | 
    
         
             
                    end
         
     | 
| 
       573 
594 
     | 
    
         
             
                  end
         
     | 
| 
       574 
595 
     | 
    
         | 
| 
      
 596 
     | 
    
         
            +
                  # Disconnect all connections that have been idle for at least
         
     | 
| 
      
 597 
     | 
    
         
            +
                  # +minimum_idle+ seconds. Connections currently checked out, or that were
         
     | 
| 
      
 598 
     | 
    
         
            +
                  # checked in less than +minimum_idle+ seconds ago, are unaffected.
         
     | 
| 
      
 599 
     | 
    
         
            +
                  def flush(minimum_idle = @idle_timeout)
         
     | 
| 
      
 600 
     | 
    
         
            +
                    return if minimum_idle.nil?
         
     | 
| 
      
 601 
     | 
    
         
            +
             
     | 
| 
      
 602 
     | 
    
         
            +
                    idle_connections = synchronize do
         
     | 
| 
      
 603 
     | 
    
         
            +
                      @connections.select do |conn|
         
     | 
| 
      
 604 
     | 
    
         
            +
                        !conn.in_use? && conn.seconds_idle >= minimum_idle
         
     | 
| 
      
 605 
     | 
    
         
            +
                      end.each do |conn|
         
     | 
| 
      
 606 
     | 
    
         
            +
                        conn.lease
         
     | 
| 
      
 607 
     | 
    
         
            +
             
     | 
| 
      
 608 
     | 
    
         
            +
                        @available.delete conn
         
     | 
| 
      
 609 
     | 
    
         
            +
                        @connections.delete conn
         
     | 
| 
      
 610 
     | 
    
         
            +
                      end
         
     | 
| 
      
 611 
     | 
    
         
            +
                    end
         
     | 
| 
      
 612 
     | 
    
         
            +
             
     | 
| 
      
 613 
     | 
    
         
            +
                    idle_connections.each do |conn|
         
     | 
| 
      
 614 
     | 
    
         
            +
                      conn.disconnect!
         
     | 
| 
      
 615 
     | 
    
         
            +
                    end
         
     | 
| 
      
 616 
     | 
    
         
            +
                  end
         
     | 
| 
      
 617 
     | 
    
         
            +
             
     | 
| 
      
 618 
     | 
    
         
            +
                  # Disconnect all currently idle connections. Connections currently checked
         
     | 
| 
      
 619 
     | 
    
         
            +
                  # out are unaffected.
         
     | 
| 
      
 620 
     | 
    
         
            +
                  def flush!
         
     | 
| 
      
 621 
     | 
    
         
            +
                    reap
         
     | 
| 
      
 622 
     | 
    
         
            +
                    flush(-1)
         
     | 
| 
      
 623 
     | 
    
         
            +
                  end
         
     | 
| 
      
 624 
     | 
    
         
            +
             
     | 
| 
       575 
625 
     | 
    
         
             
                  def num_waiting_in_queue # :nodoc:
         
     | 
| 
       576 
626 
     | 
    
         
             
                    @available.num_waiting
         
     | 
| 
       577 
627 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -679,7 +729,7 @@ module ActiveRecord 
     | 
|
| 
       679 
729 
     | 
    
         
             
                      # this block can't be easily moved into attempt_to_checkout_all_existing_connections's
         
     | 
| 
       680 
730 
     | 
    
         
             
                      # rescue block, because doing so would put it outside of synchronize section, without
         
     | 
| 
       681 
731 
     | 
    
         
             
                      # being in a critical section thread_report might become inaccurate
         
     | 
| 
       682 
     | 
    
         
            -
                      msg = "could not obtain ownership of all database connections in #{checkout_timeout} seconds"
         
     | 
| 
      
 732 
     | 
    
         
            +
                      msg = "could not obtain ownership of all database connections in #{checkout_timeout} seconds".dup
         
     | 
| 
       683 
733 
     | 
    
         | 
| 
       684 
734 
     | 
    
         
             
                      thread_report = []
         
     | 
| 
       685 
735 
     | 
    
         
             
                      @connections.each do |conn|
         
     | 
| 
         @@ -734,10 +784,10 @@ module ActiveRecord 
     | 
|
| 
       734 
784 
     | 
    
         
             
                    # Implementation detail: the connection returned by +acquire_connection+
         
     | 
| 
       735 
785 
     | 
    
         
             
                    # will already be "+connection.lease+ -ed" to the current thread.
         
     | 
| 
       736 
786 
     | 
    
         
             
                    def acquire_connection(checkout_timeout)
         
     | 
| 
       737 
     | 
    
         
            -
                      # NOTE: we rely on  
     | 
| 
      
 787 
     | 
    
         
            +
                      # NOTE: we rely on <tt>@available.poll</tt> and +try_to_checkout_new_connection+ to
         
     | 
| 
       738 
788 
     | 
    
         
             
                      # +conn.lease+ the returned connection (and to do this in a +synchronized+
         
     | 
| 
       739 
789 
     | 
    
         
             
                      # section). This is not the cleanest implementation, as ideally we would
         
     | 
| 
       740 
     | 
    
         
            -
                      # <tt>synchronize { conn.lease }</tt> in this method, but by leaving it to  
     | 
| 
      
 790 
     | 
    
         
            +
                      # <tt>synchronize { conn.lease }</tt> in this method, but by leaving it to <tt>@available.poll</tt>
         
     | 
| 
       741 
791 
     | 
    
         
             
                      # and +try_to_checkout_new_connection+ we can piggyback on +synchronize+ sections
         
     | 
| 
       742 
792 
     | 
    
         
             
                      # of the said methods and avoid an additional +synchronize+ overhead.
         
     | 
| 
       743 
793 
     | 
    
         
             
                      if conn = @available.poll || try_to_checkout_new_connection
         
     | 
| 
         @@ -761,7 +811,7 @@ module ActiveRecord 
     | 
|
| 
       761 
811 
     | 
    
         
             
                      end
         
     | 
| 
       762 
812 
     | 
    
         
             
                    end
         
     | 
| 
       763 
813 
     | 
    
         | 
| 
       764 
     | 
    
         
            -
                    # If the pool is not at a  
     | 
| 
      
 814 
     | 
    
         
            +
                    # If the pool is not at a <tt>@size</tt> limit, establish new connection. Connecting
         
     | 
| 
       765 
815 
     | 
    
         
             
                    # to the DB is done outside main synchronized section.
         
     | 
| 
       766 
816 
     | 
    
         
             
                    #--
         
     | 
| 
       767 
817 
     | 
    
         
             
                    # Implementation constraint: a newly established connection returned by this
         
     | 
| 
         @@ -827,7 +877,7 @@ module ActiveRecord 
     | 
|
| 
       827 
877 
     | 
    
         
             
                #   end
         
     | 
| 
       828 
878 
     | 
    
         
             
                #
         
     | 
| 
       829 
879 
     | 
    
         
             
                #   class Book < ActiveRecord::Base
         
     | 
| 
       830 
     | 
    
         
            -
                #     establish_connection  
     | 
| 
      
 880 
     | 
    
         
            +
                #     establish_connection :library_db
         
     | 
| 
       831 
881 
     | 
    
         
             
                #   end
         
     | 
| 
       832 
882 
     | 
    
         
             
                #
         
     | 
| 
       833 
883 
     | 
    
         
             
                #   class ScaryBook < Book
         
     | 
| 
         @@ -859,15 +909,35 @@ module ActiveRecord 
     | 
|
| 
       859 
909 
     | 
    
         
             
                # All Active Record models use this handler to determine the connection pool that they
         
     | 
| 
       860 
910 
     | 
    
         
             
                # should use.
         
     | 
| 
       861 
911 
     | 
    
         
             
                #
         
     | 
| 
       862 
     | 
    
         
            -
                # The ConnectionHandler class is not coupled with the Active models, as it has no  
     | 
| 
      
 912 
     | 
    
         
            +
                # The ConnectionHandler class is not coupled with the Active models, as it has no knowledge
         
     | 
| 
       863 
913 
     | 
    
         
             
                # about the model. The model needs to pass a specification name to the handler,
         
     | 
| 
       864 
     | 
    
         
            -
                # in order to  
     | 
| 
      
 914 
     | 
    
         
            +
                # in order to look up the correct connection pool.
         
     | 
| 
       865 
915 
     | 
    
         
             
                class ConnectionHandler
         
     | 
| 
      
 916 
     | 
    
         
            +
                  def self.unowned_pool_finalizer(pid_map) # :nodoc:
         
     | 
| 
      
 917 
     | 
    
         
            +
                    lambda do |_|
         
     | 
| 
      
 918 
     | 
    
         
            +
                      discard_unowned_pools(pid_map)
         
     | 
| 
      
 919 
     | 
    
         
            +
                    end
         
     | 
| 
      
 920 
     | 
    
         
            +
                  end
         
     | 
| 
      
 921 
     | 
    
         
            +
             
     | 
| 
      
 922 
     | 
    
         
            +
                  def self.discard_unowned_pools(pid_map) # :nodoc:
         
     | 
| 
      
 923 
     | 
    
         
            +
                    pid_map.each do |pid, pools|
         
     | 
| 
      
 924 
     | 
    
         
            +
                      pools.values.compact.each(&:discard!) unless pid == Process.pid
         
     | 
| 
      
 925 
     | 
    
         
            +
                    end
         
     | 
| 
      
 926 
     | 
    
         
            +
                  end
         
     | 
| 
      
 927 
     | 
    
         
            +
             
     | 
| 
       866 
928 
     | 
    
         
             
                  def initialize
         
     | 
| 
       867 
929 
     | 
    
         
             
                    # These caches are keyed by spec.name (ConnectionSpecification#name).
         
     | 
| 
       868 
930 
     | 
    
         
             
                    @owner_to_pool = Concurrent::Map.new(initial_capacity: 2) do |h, k|
         
     | 
| 
      
 931 
     | 
    
         
            +
                      # Discard the parent's connection pools immediately; we have no need
         
     | 
| 
      
 932 
     | 
    
         
            +
                      # of them
         
     | 
| 
      
 933 
     | 
    
         
            +
                      ConnectionHandler.discard_unowned_pools(h)
         
     | 
| 
      
 934 
     | 
    
         
            +
             
     | 
| 
       869 
935 
     | 
    
         
             
                      h[k] = Concurrent::Map.new(initial_capacity: 2)
         
     | 
| 
       870 
936 
     | 
    
         
             
                    end
         
     | 
| 
      
 937 
     | 
    
         
            +
             
     | 
| 
      
 938 
     | 
    
         
            +
                    # Backup finalizer: if the forked child never needed a pool, the above
         
     | 
| 
      
 939 
     | 
    
         
            +
                    # early discard has not occurred
         
     | 
| 
      
 940 
     | 
    
         
            +
                    ObjectSpace.define_finalizer self, ConnectionHandler.unowned_pool_finalizer(@owner_to_pool)
         
     | 
| 
       871 
941 
     | 
    
         
             
                  end
         
     | 
| 
       872 
942 
     | 
    
         | 
| 
       873 
943 
     | 
    
         
             
                  def connection_pool_list
         
     | 
| 
         @@ -921,6 +991,13 @@ module ActiveRecord 
     | 
|
| 
       921 
991 
     | 
    
         
             
                    connection_pool_list.each(&:disconnect!)
         
     | 
| 
       922 
992 
     | 
    
         
             
                  end
         
     | 
| 
       923 
993 
     | 
    
         | 
| 
      
 994 
     | 
    
         
            +
                  # Disconnects all currently idle connections.
         
     | 
| 
      
 995 
     | 
    
         
            +
                  #
         
     | 
| 
      
 996 
     | 
    
         
            +
                  # See ConnectionPool#flush! for details.
         
     | 
| 
      
 997 
     | 
    
         
            +
                  def flush_idle_connections!
         
     | 
| 
      
 998 
     | 
    
         
            +
                    connection_pool_list.each(&:flush!)
         
     | 
| 
      
 999 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1000 
     | 
    
         
            +
             
     | 
| 
       924 
1001 
     | 
    
         
             
                  # Locate the connection of the nearest super class. This can be an
         
     | 
| 
       925 
1002 
     | 
    
         
             
                  # active or defined connection: if it is the latter, it will be
         
     | 
| 
       926 
1003 
     | 
    
         
             
                  # opened and set as the active connection for the class it was defined
         
     | 
| 
         @@ -928,9 +1005,7 @@ module ActiveRecord 
     | 
|
| 
       928 
1005 
     | 
    
         
             
                  def retrieve_connection(spec_name) #:nodoc:
         
     | 
| 
       929 
1006 
     | 
    
         
             
                    pool = retrieve_connection_pool(spec_name)
         
     | 
| 
       930 
1007 
     | 
    
         
             
                    raise ConnectionNotEstablished, "No connection pool with '#{spec_name}' found." unless pool
         
     | 
| 
       931 
     | 
    
         
            -
                     
     | 
| 
       932 
     | 
    
         
            -
                    raise ConnectionNotEstablished, "No connection for '#{spec_name}' in connection pool" unless conn
         
     | 
| 
       933 
     | 
    
         
            -
                    conn
         
     | 
| 
      
 1008 
     | 
    
         
            +
                    pool.connection
         
     | 
| 
       934 
1009 
     | 
    
         
             
                  end
         
     | 
| 
       935 
1010 
     | 
    
         | 
| 
       936 
1011 
     | 
    
         
             
                  # Returns true if a connection that's accessible to this class has
         
     |