activerecord 5.2.4.4 → 6.0.3.4
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 +777 -552
- data/MIT-LICENSE +3 -1
- data/README.rdoc +5 -3
- data/examples/performance.rb +1 -1
- data/lib/active_record.rb +10 -2
- data/lib/active_record/advisory_lock_base.rb +18 -0
- data/lib/active_record/aggregations.rb +4 -3
- data/lib/active_record/association_relation.rb +10 -8
- data/lib/active_record/associations.rb +21 -16
- data/lib/active_record/associations/alias_tracker.rb +0 -1
- data/lib/active_record/associations/association.rb +56 -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 -40
- 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 +12 -23
- data/lib/active_record/associations/collection_proxy.rb +13 -17
- data/lib/active_record/associations/foreign_association.rb +7 -0
- data/lib/active_record/associations/has_many_association.rb +2 -11
- 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 +37 -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 +39 -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 -11
- data/lib/active_record/attribute_decorators.rb +0 -2
- data/lib/active_record/attribute_methods.rb +28 -100
- data/lib/active_record/attribute_methods/before_type_cast.rb +4 -2
- data/lib/active_record/attribute_methods/dirty.rb +111 -40
- data/lib/active_record/attribute_methods/primary_key.rb +15 -24
- data/lib/active_record/attribute_methods/query.rb +2 -3
- data/lib/active_record/attribute_methods/read.rb +15 -54
- data/lib/active_record/attribute_methods/serialization.rb +1 -2
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -3
- data/lib/active_record/attribute_methods/write.rb +17 -25
- data/lib/active_record/attributes.rb +13 -1
- data/lib/active_record/autosave_association.rb +3 -5
- data/lib/active_record/base.rb +2 -3
- data/lib/active_record/callbacks.rb +6 -21
- data/lib/active_record/coders/yaml_column.rb +0 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +103 -18
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -4
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +102 -124
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -9
- data/lib/active_record/connection_adapters/abstract/quoting.rb +68 -17
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +20 -14
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +100 -72
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +175 -79
- data/lib/active_record/connection_adapters/abstract/transaction.rb +96 -57
- data/lib/active_record/connection_adapters/abstract_adapter.rb +191 -43
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +142 -215
- data/lib/active_record/connection_adapters/column.rb +17 -13
- data/lib/active_record/connection_adapters/connection_specification.rb +54 -45
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +6 -10
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +70 -14
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +0 -1
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +4 -6
- 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 +132 -16
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +6 -10
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +26 -10
- data/lib/active_record/connection_adapters/postgresql/column.rb +17 -31
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +26 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +44 -7
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +14 -3
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +63 -75
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +24 -27
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +168 -75
- 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 +119 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -12
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +135 -146
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_handling.rb +139 -26
- data/lib/active_record/core.rb +103 -61
- data/lib/active_record/counter_cache.rb +8 -30
- 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 +78 -0
- data/lib/active_record/dynamic_matchers.rb +3 -4
- data/lib/active_record/enum.rb +37 -7
- data/lib/active_record/errors.rb +15 -7
- data/lib/active_record/explain.rb +1 -2
- 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 +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +144 -474
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +13 -6
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +68 -16
- data/lib/active_record/internal_metadata.rb +11 -3
- data/lib/active_record/locking/optimistic.rb +5 -7
- data/lib/active_record/locking/pessimistic.rb +3 -3
- data/lib/active_record/log_subscriber.rb +8 -27
- data/lib/active_record/middleware/database_selector.rb +74 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/migration.rb +104 -85
- data/lib/active_record/migration/command_recorder.rb +54 -22
- data/lib/active_record/migration/compatibility.rb +79 -52
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/model_schema.rb +33 -11
- data/lib/active_record/nested_attributes.rb +2 -4
- data/lib/active_record/no_touching.rb +9 -2
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +232 -29
- data/lib/active_record/query_cache.rb +11 -4
- data/lib/active_record/querying.rb +33 -21
- 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 +199 -46
- data/lib/active_record/reflection.rb +40 -38
- data/lib/active_record/relation.rb +322 -80
- data/lib/active_record/relation/batches.rb +13 -11
- data/lib/active_record/relation/calculations.rb +54 -48
- data/lib/active_record/relation/delegation.rb +33 -49
- data/lib/active_record/relation/finder_methods.rb +23 -28
- data/lib/active_record/relation/from_clause.rb +4 -0
- data/lib/active_record/relation/merger.rb +11 -21
- data/lib/active_record/relation/predicate_builder.rb +5 -11
- 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 +221 -70
- data/lib/active_record/relation/spawn_methods.rb +1 -2
- data/lib/active_record/relation/where_clause.rb +14 -11
- data/lib/active_record/relation/where_clause_factory.rb +1 -2
- data/lib/active_record/result.rb +30 -12
- 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 +6 -2
- data/lib/active_record/scoping.rb +8 -9
- data/lib/active_record/scoping/default.rb +4 -6
- data/lib/active_record/scoping/named.rb +21 -17
- data/lib/active_record/statement_cache.rb +30 -3
- data/lib/active_record/store.rb +87 -8
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +23 -15
- data/lib/active_record/tasks/database_tasks.rb +194 -25
- data/lib/active_record/tasks/mysql_database_tasks.rb +5 -6
- data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -8
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -9
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +225 -0
- data/lib/active_record/timestamp.rb +39 -26
- data/lib/active_record/touch_later.rb +5 -4
- data/lib/active_record/transactions.rb +64 -73
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type.rb +3 -5
- data/lib/active_record/type/adapter_specific_registry.rb +3 -13
- data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
- data/lib/active_record/type/serialized.rb +0 -1
- data/lib/active_record/type/type_map.rb +0 -1
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type_caster/connection.rb +15 -14
- data/lib/active_record/type_caster/map.rb +1 -4
- data/lib/active_record/validations.rb +3 -3
- data/lib/active_record/validations/associated.rb +1 -2
- data/lib/active_record/validations/uniqueness.rb +15 -27
- data/lib/arel.rb +62 -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 +256 -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 +203 -0
- data/lib/arel/visitors/dot.rb +296 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +156 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +158 -0
- data/lib/arel/visitors/oracle12.rb +65 -0
- data/lib/arel/visitors/postgresql.rb +109 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +888 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors/where_sql.rb +22 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration.rb +14 -2
- 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 -1
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
- metadata +115 -29
- data/lib/active_record/collection_cache_key.rb +0 -53
    
        data/MIT-LICENSE
    CHANGED
    
    | @@ -1,4 +1,6 @@ | |
| 1 | 
            -
            Copyright (c) 2004- | 
| 1 | 
            +
            Copyright (c) 2004-2019 David Heinemeier Hansson
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Arel originally copyright (c) 2007-2016 Nick Kallen, Bryan Helmkamp, Emilio Tagua, Aaron Patterson
         | 
| 2 4 |  | 
| 3 5 | 
             
            Permission is hereby granted, free of charge, to any person obtaining
         | 
| 4 6 | 
             
            a copy of this software and associated documentation files (the
         | 
    
        data/README.rdoc
    CHANGED
    
    | @@ -13,6 +13,8 @@ columns. Although these mappings can be defined explicitly, it's recommended | |
| 13 13 | 
             
            to follow naming conventions, especially when getting started with the
         | 
| 14 14 | 
             
            library.
         | 
| 15 15 |  | 
| 16 | 
            +
            You can read more about Active Record in the {Active Record Basics}[https://edgeguides.rubyonrails.org/active_record_basics.html] guide.
         | 
| 17 | 
            +
             | 
| 16 18 | 
             
            A short rundown of some of the major features:
         | 
| 17 19 |  | 
| 18 20 | 
             
            * Automated mapping between classes and tables, attributes and columns.
         | 
| @@ -192,7 +194,7 @@ The latest version of Active Record can be installed with RubyGems: | |
| 192 194 |  | 
| 193 195 | 
             
            Source code can be downloaded as part of the Rails project on GitHub:
         | 
| 194 196 |  | 
| 195 | 
            -
            * https://github.com/rails/rails/tree/ | 
| 197 | 
            +
            * https://github.com/rails/rails/tree/master/activerecord
         | 
| 196 198 |  | 
| 197 199 |  | 
| 198 200 | 
             
            == License
         | 
| @@ -206,7 +208,7 @@ Active Record is released under the MIT license: | |
| 206 208 |  | 
| 207 209 | 
             
            API documentation is at:
         | 
| 208 210 |  | 
| 209 | 
            -
            *  | 
| 211 | 
            +
            * https://api.rubyonrails.org
         | 
| 210 212 |  | 
| 211 213 | 
             
            Bug reports for the Ruby on Rails project can be filed here:
         | 
| 212 214 |  | 
| @@ -214,4 +216,4 @@ Bug reports for the Ruby on Rails project can be filed here: | |
| 214 216 |  | 
| 215 217 | 
             
            Feature requests should be discussed on the rails-core mailing list here:
         | 
| 216 218 |  | 
| 217 | 
            -
            * https:// | 
| 219 | 
            +
            * https://discuss.rubyonrails.org/c/rubyonrails-core
         | 
    
        data/examples/performance.rb
    CHANGED
    
    
    
        data/lib/active_record.rb
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 3 | 
             
            #--
         | 
| 4 | 
            -
            # Copyright (c) 2004- | 
| 4 | 
            +
            # Copyright (c) 2004-2019 David Heinemeier Hansson
         | 
| 5 5 | 
             
            #
         | 
| 6 6 | 
             
            # Permission is hereby granted, free of charge, to any person obtaining
         | 
| 7 7 | 
             
            # a copy of this software and associated documentation files (the
         | 
| @@ -35,6 +35,7 @@ require "active_model/attribute_set" | |
| 35 35 | 
             
            module ActiveRecord
         | 
| 36 36 | 
             
              extend ActiveSupport::Autoload
         | 
| 37 37 |  | 
| 38 | 
            +
              autoload :AdvisoryLockBase
         | 
| 38 39 | 
             
              autoload :Base
         | 
| 39 40 | 
             
              autoload :Callbacks
         | 
| 40 41 | 
             
              autoload :Core
         | 
| @@ -55,7 +56,6 @@ module ActiveRecord | |
| 55 56 | 
             
              autoload :Persistence
         | 
| 56 57 | 
             
              autoload :QueryCache
         | 
| 57 58 | 
             
              autoload :Querying
         | 
| 58 | 
            -
              autoload :CollectionCacheKey
         | 
| 59 59 | 
             
              autoload :ReadonlyAttributes
         | 
| 60 60 | 
             
              autoload :RecordInvalid, "active_record/validations"
         | 
| 61 61 | 
             
              autoload :Reflection
         | 
| @@ -74,6 +74,7 @@ module ActiveRecord | |
| 74 74 | 
             
              autoload :Translation
         | 
| 75 75 | 
             
              autoload :Validations
         | 
| 76 76 | 
             
              autoload :SecureToken
         | 
| 77 | 
            +
              autoload :DatabaseSelector, "active_record/middleware/database_selector"
         | 
| 77 78 |  | 
| 78 79 | 
             
              eager_autoload do
         | 
| 79 80 | 
             
                autoload :ActiveRecordError, "active_record/errors"
         | 
| @@ -153,6 +154,12 @@ module ActiveRecord | |
| 153 154 | 
             
                end
         | 
| 154 155 | 
             
              end
         | 
| 155 156 |  | 
| 157 | 
            +
              module Middleware
         | 
| 158 | 
            +
                extend ActiveSupport::Autoload
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                autoload :DatabaseSelector, "active_record/middleware/database_selector"
         | 
| 161 | 
            +
              end
         | 
| 162 | 
            +
             | 
| 156 163 | 
             
              module Tasks
         | 
| 157 164 | 
             
                extend ActiveSupport::Autoload
         | 
| 158 165 |  | 
| @@ -163,6 +170,7 @@ module ActiveRecord | |
| 163 170 | 
             
                  "active_record/tasks/postgresql_database_tasks"
         | 
| 164 171 | 
             
              end
         | 
| 165 172 |  | 
| 173 | 
            +
              autoload :TestDatabases, "active_record/test_databases"
         | 
| 166 174 | 
             
              autoload :TestFixtures, "active_record/fixtures"
         | 
| 167 175 |  | 
| 168 176 | 
             
              def self.eager_load!
         | 
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module ActiveRecord
         | 
| 4 | 
            +
              # This class is used to create a connection that we can use for advisory
         | 
| 5 | 
            +
              # locks. This will take out a "global" lock that can't be accidentally
         | 
| 6 | 
            +
              # removed if a new connection is established during a migration.
         | 
| 7 | 
            +
              class AdvisoryLockBase < ActiveRecord::Base # :nodoc:
         | 
| 8 | 
            +
                self.abstract_class = true
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                self.connection_specification_name = "AdvisoryLockBase"
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                class << self
         | 
| 13 | 
            +
                  def _internal?
         | 
| 14 | 
            +
                    true
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
            end
         | 
| @@ -3,8 +3,6 @@ | |
| 3 3 | 
             
            module ActiveRecord
         | 
| 4 4 | 
             
              # See ActiveRecord::Aggregations::ClassMethods for documentation
         | 
| 5 5 | 
             
              module Aggregations
         | 
| 6 | 
            -
                extend ActiveSupport::Concern
         | 
| 7 | 
            -
             | 
| 8 6 | 
             
                def initialize_dup(*) # :nodoc:
         | 
| 9 7 | 
             
                  @aggregation_cache = {}
         | 
| 10 8 | 
             
                  super
         | 
| @@ -16,7 +14,6 @@ module ActiveRecord | |
| 16 14 | 
             
                end
         | 
| 17 15 |  | 
| 18 16 | 
             
                private
         | 
| 19 | 
            -
             | 
| 20 17 | 
             
                  def clear_aggregation_cache
         | 
| 21 18 | 
             
                    @aggregation_cache.clear if persisted?
         | 
| 22 19 | 
             
                  end
         | 
| @@ -225,6 +222,10 @@ module ActiveRecord | |
| 225 222 | 
             
                    def composed_of(part_id, options = {})
         | 
| 226 223 | 
             
                      options.assert_valid_keys(:class_name, :mapping, :allow_nil, :constructor, :converter)
         | 
| 227 224 |  | 
| 225 | 
            +
                      unless self < Aggregations
         | 
| 226 | 
            +
                        include Aggregations
         | 
| 227 | 
            +
                      end
         | 
| 228 | 
            +
             | 
| 228 229 | 
             
                      name        = part_id.id2name
         | 
| 229 230 | 
             
                      class_name  = options[:class_name]  || name.camelize
         | 
| 230 231 | 
             
                      mapping     = options[:mapping]     || [ name, name ]
         | 
| @@ -2,7 +2,7 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            module ActiveRecord
         | 
| 4 4 | 
             
              class AssociationRelation < Relation
         | 
| 5 | 
            -
                def initialize(klass, association)
         | 
| 5 | 
            +
                def initialize(klass, association, **)
         | 
| 6 6 | 
             
                  super(klass)
         | 
| 7 7 | 
             
                  @association = association
         | 
| 8 8 | 
             
                end
         | 
| @@ -15,21 +15,23 @@ module ActiveRecord | |
| 15 15 | 
             
                  other == records
         | 
| 16 16 | 
             
                end
         | 
| 17 17 |  | 
| 18 | 
            -
                def build( | 
| 19 | 
            -
                   | 
| 18 | 
            +
                def build(attributes = nil, &block)
         | 
| 19 | 
            +
                  block = _deprecated_scope_block("new", &block)
         | 
| 20 | 
            +
                  scoping { @association.build(attributes, &block) }
         | 
| 20 21 | 
             
                end
         | 
| 21 22 | 
             
                alias new build
         | 
| 22 23 |  | 
| 23 | 
            -
                def create( | 
| 24 | 
            -
                   | 
| 24 | 
            +
                def create(attributes = nil, &block)
         | 
| 25 | 
            +
                  block = _deprecated_scope_block("create", &block)
         | 
| 26 | 
            +
                  scoping { @association.create(attributes, &block) }
         | 
| 25 27 | 
             
                end
         | 
| 26 28 |  | 
| 27 | 
            -
                def create!( | 
| 28 | 
            -
                   | 
| 29 | 
            +
                def create!(attributes = nil, &block)
         | 
| 30 | 
            +
                  block = _deprecated_scope_block("create!", &block)
         | 
| 31 | 
            +
                  scoping { @association.create!(attributes, &block) }
         | 
| 29 32 | 
             
                end
         | 
| 30 33 |  | 
| 31 34 | 
             
                private
         | 
| 32 | 
            -
             | 
| 33 35 | 
             
                  def exec_queries
         | 
| 34 36 | 
             
                    super do |record|
         | 
| 35 37 | 
             
                      @association.set_inverse_instance_from_queries(record)
         | 
| @@ -92,7 +92,7 @@ module ActiveRecord | |
| 92 92 | 
             
                    through_reflection      = reflection.through_reflection
         | 
| 93 93 | 
             
                    source_reflection_names = reflection.source_reflection_names
         | 
| 94 94 | 
             
                    source_associations     = reflection.through_reflection.klass._reflections.keys
         | 
| 95 | 
            -
                    super("Could not find the source association(s) #{source_reflection_names.collect(&:inspect).to_sentence(two_words_connector: ' or ', last_word_connector: ', or ' | 
| 95 | 
            +
                    super("Could not find the source association(s) #{source_reflection_names.collect(&:inspect).to_sentence(two_words_connector: ' or ', last_word_connector: ', or ')} in model #{through_reflection.klass}. Try 'has_many #{reflection.name.inspect}, :through => #{through_reflection.name.inspect}, :source => <name>'. Is it one of #{source_associations.to_sentence(two_words_connector: ' or ', last_word_connector: ', or ')}?")
         | 
| 96 96 | 
             
                  else
         | 
| 97 97 | 
             
                    super("Could not find the source association(s).")
         | 
| 98 98 | 
             
                  end
         | 
| @@ -292,13 +292,13 @@ module ActiveRecord | |
| 292 292 | 
             
                  #
         | 
| 293 293 | 
             
                  # The project class now has the following methods (and more) to ease the traversal and
         | 
| 294 294 | 
             
                  # manipulation of its relationships:
         | 
| 295 | 
            -
                  # * <tt>Project#portfolio | 
| 296 | 
            -
                  # * <tt>Project#project_manager | 
| 297 | 
            -
                  # * <tt>Project#milestones.empty | 
| 298 | 
            -
                  #   <tt>Project#milestones.delete(milestone) | 
| 299 | 
            -
                  #   <tt>Project#milestones.build | 
| 300 | 
            -
                  # * <tt>Project#categories.empty | 
| 301 | 
            -
                  #   <tt>Project#categories.delete(category1) | 
| 295 | 
            +
                  # * <tt>Project#portfolio</tt>, <tt>Project#portfolio=(portfolio)</tt>, <tt>Project#reload_portfolio</tt>
         | 
| 296 | 
            +
                  # * <tt>Project#project_manager</tt>, <tt>Project#project_manager=(project_manager)</tt>, <tt>Project#reload_project_manager</tt>
         | 
| 297 | 
            +
                  # * <tt>Project#milestones.empty?</tt>, <tt>Project#milestones.size</tt>, <tt>Project#milestones</tt>, <tt>Project#milestones<<(milestone)</tt>,
         | 
| 298 | 
            +
                  #   <tt>Project#milestones.delete(milestone)</tt>, <tt>Project#milestones.destroy(milestone)</tt>, <tt>Project#milestones.find(milestone_id)</tt>,
         | 
| 299 | 
            +
                  #   <tt>Project#milestones.build</tt>, <tt>Project#milestones.create</tt>
         | 
| 300 | 
            +
                  # * <tt>Project#categories.empty?</tt>, <tt>Project#categories.size</tt>, <tt>Project#categories</tt>, <tt>Project#categories<<(category1)</tt>,
         | 
| 301 | 
            +
                  #   <tt>Project#categories.delete(category1)</tt>, <tt>Project#categories.destroy(category1)</tt>
         | 
| 302 302 | 
             
                  #
         | 
| 303 303 | 
             
                  # === A word of warning
         | 
| 304 304 | 
             
                  #
         | 
| @@ -703,8 +703,9 @@ module ActiveRecord | |
| 703 703 | 
             
                  # #belongs_to associations.
         | 
| 704 704 | 
             
                  #
         | 
| 705 705 | 
             
                  # Extra options on the associations, as defined in the
         | 
| 706 | 
            -
                  # <tt>AssociationReflection::INVALID_AUTOMATIC_INVERSE_OPTIONS</tt> | 
| 707 | 
            -
                  # also prevent the association's inverse | 
| 706 | 
            +
                  # <tt>AssociationReflection::INVALID_AUTOMATIC_INVERSE_OPTIONS</tt>
         | 
| 707 | 
            +
                  # constant, or a custom scope, will also prevent the association's inverse
         | 
| 708 | 
            +
                  # from being found automatically.
         | 
| 708 709 | 
             
                  #
         | 
| 709 710 | 
             
                  # The automatic guessing of the inverse association uses a heuristic based
         | 
| 710 711 | 
             
                  # on the name of the class, so it may not work for all associations,
         | 
| @@ -1293,8 +1294,9 @@ module ActiveRecord | |
| 1293 1294 | 
             
                    #
         | 
| 1294 1295 | 
             
                    #   * <tt>:destroy</tt> causes all the associated objects to also be destroyed.
         | 
| 1295 1296 | 
             
                    #   * <tt>:delete_all</tt> causes all the associated objects to be deleted directly from the database (so callbacks will not be executed).
         | 
| 1296 | 
            -
                    #   * <tt>:nullify</tt> causes the foreign keys to be set to +NULL+.  | 
| 1297 | 
            -
                    # | 
| 1297 | 
            +
                    #   * <tt>:nullify</tt> causes the foreign keys to be set to +NULL+. Polymorphic type will also be nullified
         | 
| 1298 | 
            +
                    #     on polymorphic associations. Callbacks are not executed.
         | 
| 1299 | 
            +
                    #   * <tt>:restrict_with_exception</tt> causes an <tt>ActiveRecord::DeleteRestrictionError</tt> exception to be raised if there are any associated records.
         | 
| 1298 1300 | 
             
                    #   * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there are any associated objects.
         | 
| 1299 1301 | 
             
                    #
         | 
| 1300 1302 | 
             
                    #   If using with the <tt>:through</tt> option, the association on the join model must be
         | 
| @@ -1436,8 +1438,9 @@ module ActiveRecord | |
| 1436 1438 | 
             
                    #
         | 
| 1437 1439 | 
             
                    #   * <tt>:destroy</tt> causes the associated object to also be destroyed
         | 
| 1438 1440 | 
             
                    #   * <tt>:delete</tt> causes the associated object to be deleted directly from the database (so callbacks will not execute)
         | 
| 1439 | 
            -
                    #   * <tt>:nullify</tt> causes the foreign key to be set to +NULL+.  | 
| 1440 | 
            -
                    # | 
| 1441 | 
            +
                    #   * <tt>:nullify</tt> causes the foreign key to be set to +NULL+. Polymorphic type column is also nullified
         | 
| 1442 | 
            +
                    #     on polymorphic associations. Callbacks are not executed.
         | 
| 1443 | 
            +
                    #   * <tt>:restrict_with_exception</tt> causes an <tt>ActiveRecord::DeleteRestrictionError</tt> exception to be raised if there is an associated record
         | 
| 1441 1444 | 
             
                    #   * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there is an associated object
         | 
| 1442 1445 | 
             
                    #
         | 
| 1443 1446 | 
             
                    #   Note that <tt>:dependent</tt> option is ignored when using <tt>:through</tt> option.
         | 
| @@ -1524,6 +1527,7 @@ module ActiveRecord | |
| 1524 1527 | 
             
                    #   Returns the associated object. +nil+ is returned if none is found.
         | 
| 1525 1528 | 
             
                    # [association=(associate)]
         | 
| 1526 1529 | 
             
                    #   Assigns the associate object, extracts the primary key, and sets it as the foreign key.
         | 
| 1530 | 
            +
                    #   No modification or deletion of existing records takes place.
         | 
| 1527 1531 | 
             
                    # [build_association(attributes = {})]
         | 
| 1528 1532 | 
             
                    #   Returns a new object of the associated type that has been instantiated
         | 
| 1529 1533 | 
             
                    #   with +attributes+ and linked to this object through a foreign key, but has not yet been saved.
         | 
| @@ -1581,7 +1585,7 @@ module ActiveRecord | |
| 1581 1585 | 
             
                    #   association will use "taggable_type" as the default <tt>:foreign_type</tt>.
         | 
| 1582 1586 | 
             
                    # [:primary_key]
         | 
| 1583 1587 | 
             
                    #   Specify the method that returns the primary key of associated object used for the association.
         | 
| 1584 | 
            -
                    #   By default this is id | 
| 1588 | 
            +
                    #   By default this is +id+.
         | 
| 1585 1589 | 
             
                    # [:dependent]
         | 
| 1586 1590 | 
             
                    #   If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
         | 
| 1587 1591 | 
             
                    #   <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method.
         | 
| @@ -1761,6 +1765,7 @@ module ActiveRecord | |
| 1761 1765 | 
             
                    #   has_and_belongs_to_many :projects, -> { includes(:milestones, :manager) }
         | 
| 1762 1766 | 
             
                    #   has_and_belongs_to_many :categories, ->(post) {
         | 
| 1763 1767 | 
             
                    #     where("default_category = ?", post.default_category)
         | 
| 1768 | 
            +
                    #   }
         | 
| 1764 1769 | 
             
                    #
         | 
| 1765 1770 | 
             
                    # === Extensions
         | 
| 1766 1771 | 
             
                    #
         | 
| @@ -1852,7 +1857,7 @@ module ActiveRecord | |
| 1852 1857 | 
             
                        hm_options[k] = options[k] if options.key? k
         | 
| 1853 1858 | 
             
                      end
         | 
| 1854 1859 |  | 
| 1855 | 
            -
                      has_many name, scope, hm_options, &extension
         | 
| 1860 | 
            +
                      has_many name, scope, **hm_options, &extension
         | 
| 1856 1861 | 
             
                      _reflections[name.to_s].parent_reflection = habtm_reflection
         | 
| 1857 1862 | 
             
                    end
         | 
| 1858 1863 | 
             
                  end
         | 
| @@ -17,6 +17,23 @@ module ActiveRecord | |
| 17 17 | 
             
                #     CollectionAssociation
         | 
| 18 18 | 
             
                #       HasManyAssociation + ForeignAssociation
         | 
| 19 19 | 
             
                #         HasManyThroughAssociation + ThroughAssociation
         | 
| 20 | 
            +
                #
         | 
| 21 | 
            +
                # Associations in Active Record are middlemen between the object that
         | 
| 22 | 
            +
                # holds the association, known as the <tt>owner</tt>, and the associated
         | 
| 23 | 
            +
                # result set, known as the <tt>target</tt>. Association metadata is available in
         | 
| 24 | 
            +
                # <tt>reflection</tt>, which is an instance of <tt>ActiveRecord::Reflection::AssociationReflection</tt>.
         | 
| 25 | 
            +
                #
         | 
| 26 | 
            +
                # For example, given
         | 
| 27 | 
            +
                #
         | 
| 28 | 
            +
                #   class Blog < ActiveRecord::Base
         | 
| 29 | 
            +
                #     has_many :posts
         | 
| 30 | 
            +
                #   end
         | 
| 31 | 
            +
                #
         | 
| 32 | 
            +
                #   blog = Blog.first
         | 
| 33 | 
            +
                #
         | 
| 34 | 
            +
                # The association of <tt>blog.posts</tt> has the object +blog+ as its
         | 
| 35 | 
            +
                # <tt>owner</tt>, the collection of its posts as <tt>target</tt>, and
         | 
| 36 | 
            +
                # the <tt>reflection</tt> object represents a <tt>:has_many</tt> macro.
         | 
| 20 37 | 
             
                class Association #:nodoc:
         | 
| 21 38 | 
             
                  attr_reader :owner, :target, :reflection
         | 
| 22 39 |  | 
| @@ -40,7 +57,9 @@ module ActiveRecord | |
| 40 57 | 
             
                  end
         | 
| 41 58 |  | 
| 42 59 | 
             
                  # Reloads the \target and returns +self+ on success.
         | 
| 43 | 
            -
                   | 
| 60 | 
            +
                  # The QueryCache is cleared if +force+ is true.
         | 
| 61 | 
            +
                  def reload(force = false)
         | 
| 62 | 
            +
                    klass.connection.clear_query_cache if force && klass
         | 
| 44 63 | 
             
                    reset
         | 
| 45 64 | 
             
                    reset_scope
         | 
| 46 65 | 
             
                    load_target
         | 
| @@ -76,18 +95,10 @@ module ActiveRecord | |
| 76 95 | 
             
                  end
         | 
| 77 96 |  | 
| 78 97 | 
             
                  def scope
         | 
| 79 | 
            -
                     | 
| 80 | 
            -
             | 
| 81 | 
            -
             | 
| 82 | 
            -
             | 
| 83 | 
            -
                  #
         | 
| 84 | 
            -
                  # Note that the association_scope is merged into the target_scope only when the
         | 
| 85 | 
            -
                  # scope method is called. This is because at that point the call may be surrounded
         | 
| 86 | 
            -
                  # by scope.scoping { ... } or with_scope { ... } etc, which affects the scope which
         | 
| 87 | 
            -
                  # actually gets built.
         | 
| 88 | 
            -
                  def association_scope
         | 
| 89 | 
            -
                    if klass
         | 
| 90 | 
            -
                      @association_scope ||= AssociationScope.scope(self)
         | 
| 98 | 
            +
                    if (scope = klass.current_scope) && scope.try(:proxy_association) == self
         | 
| 99 | 
            +
                      scope.spawn
         | 
| 100 | 
            +
                    else
         | 
| 101 | 
            +
                      target_scope.merge!(association_scope)
         | 
| 91 102 | 
             
                    end
         | 
| 92 103 | 
             
                  end
         | 
| 93 104 |  | 
| @@ -129,12 +140,6 @@ module ActiveRecord | |
| 129 140 | 
             
                    reflection.klass
         | 
| 130 141 | 
             
                  end
         | 
| 131 142 |  | 
| 132 | 
            -
                  # Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
         | 
| 133 | 
            -
                  # through association's scope)
         | 
| 134 | 
            -
                  def target_scope
         | 
| 135 | 
            -
                    AssociationRelation.create(klass, self).merge!(klass.all)
         | 
| 136 | 
            -
                  end
         | 
| 137 | 
            -
             | 
| 138 143 | 
             
                  def extensions
         | 
| 139 144 | 
             
                    extensions = klass.default_extensions | reflection.extensions
         | 
| 140 145 |  | 
| @@ -195,6 +200,38 @@ module ActiveRecord | |
| 195 200 | 
             
                  end
         | 
| 196 201 |  | 
| 197 202 | 
             
                  private
         | 
| 203 | 
            +
                    def find_target
         | 
| 204 | 
            +
                      scope = self.scope
         | 
| 205 | 
            +
                      return scope.to_a if skip_statement_cache?(scope)
         | 
| 206 | 
            +
             | 
| 207 | 
            +
                      conn = klass.connection
         | 
| 208 | 
            +
                      sc = reflection.association_scope_cache(conn, owner) do |params|
         | 
| 209 | 
            +
                        as = AssociationScope.create { params.bind }
         | 
| 210 | 
            +
                        target_scope.merge!(as.scope(self))
         | 
| 211 | 
            +
                      end
         | 
| 212 | 
            +
             | 
| 213 | 
            +
                      binds = AssociationScope.get_bind_values(owner, reflection.chain)
         | 
| 214 | 
            +
                      sc.execute(binds, conn) { |record| set_inverse_instance(record) } || []
         | 
| 215 | 
            +
                    end
         | 
| 216 | 
            +
             | 
| 217 | 
            +
                    # The scope for this association.
         | 
| 218 | 
            +
                    #
         | 
| 219 | 
            +
                    # Note that the association_scope is merged into the target_scope only when the
         | 
| 220 | 
            +
                    # scope method is called. This is because at that point the call may be surrounded
         | 
| 221 | 
            +
                    # by scope.scoping { ... } or unscoped { ... } etc, which affects the scope which
         | 
| 222 | 
            +
                    # actually gets built.
         | 
| 223 | 
            +
                    def association_scope
         | 
| 224 | 
            +
                      if klass
         | 
| 225 | 
            +
                        @association_scope ||= AssociationScope.scope(self)
         | 
| 226 | 
            +
                      end
         | 
| 227 | 
            +
                    end
         | 
| 228 | 
            +
             | 
| 229 | 
            +
                    # Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
         | 
| 230 | 
            +
                    # through association's scope)
         | 
| 231 | 
            +
                    def target_scope
         | 
| 232 | 
            +
                      AssociationRelation.create(klass, self).merge!(klass.scope_for_association)
         | 
| 233 | 
            +
                    end
         | 
| 234 | 
            +
             | 
| 198 235 | 
             
                    def scope_for_create
         | 
| 199 236 | 
             
                      scope.scope_for_create
         | 
| 200 237 | 
             
                    end
         | 
| @@ -26,7 +26,9 @@ module ActiveRecord | |
| 26 26 | 
             
                    chain = get_chain(reflection, association, scope.alias_tracker)
         | 
| 27 27 |  | 
| 28 28 | 
             
                    scope.extending! reflection.extensions
         | 
| 29 | 
            -
                    add_constraints(scope, owner, chain)
         | 
| 29 | 
            +
                    scope = add_constraints(scope, owner, chain)
         | 
| 30 | 
            +
                    scope.limit!(1) unless reflection.collection?
         | 
| 31 | 
            +
                    scope
         | 
| 30 32 | 
             
                  end
         | 
| 31 33 |  | 
| 32 34 | 
             
                  def self.get_bind_values(owner, chain)
         | 
| @@ -46,13 +48,9 @@ module ActiveRecord | |
| 46 48 | 
             
                    binds
         | 
| 47 49 | 
             
                  end
         | 
| 48 50 |  | 
| 49 | 
            -
                   | 
| 50 | 
            -
                  # Workaround for Ruby 2.2 "private attribute?" warning.
         | 
| 51 | 
            -
                  protected
         | 
| 52 | 
            -
             | 
| 51 | 
            +
                  private
         | 
| 53 52 | 
             
                    attr_reader :value_transformation
         | 
| 54 53 |  | 
| 55 | 
            -
                  private
         | 
| 56 54 | 
             
                    def join(table, constraint)
         | 
| 57 55 | 
             
                      table.create_join(table, table.create_on(constraint))
         | 
| 58 56 | 
             
                    end
         | 
| @@ -16,21 +16,6 @@ module ActiveRecord | |
| 16 16 | 
             
                    end
         | 
| 17 17 | 
             
                  end
         | 
| 18 18 |  | 
| 19 | 
            -
                  def replace(record)
         | 
| 20 | 
            -
                    if record
         | 
| 21 | 
            -
                      raise_on_type_mismatch!(record)
         | 
| 22 | 
            -
                      update_counters_on_replace(record)
         | 
| 23 | 
            -
                      set_inverse_instance(record)
         | 
| 24 | 
            -
                      @updated = true
         | 
| 25 | 
            -
                    else
         | 
| 26 | 
            -
                      decrement_counters
         | 
| 27 | 
            -
                    end
         | 
| 28 | 
            -
             | 
| 29 | 
            -
                    replace_keys(record)
         | 
| 30 | 
            -
             | 
| 31 | 
            -
                    self.target = record
         | 
| 32 | 
            -
                  end
         | 
| 33 | 
            -
             | 
| 34 19 | 
             
                  def inversed_from(record)
         | 
| 35 20 | 
             
                    replace_keys(record)
         | 
| 36 21 | 
             
                    super
         | 
| @@ -49,30 +34,60 @@ module ActiveRecord | |
| 49 34 | 
             
                    @updated
         | 
| 50 35 | 
             
                  end
         | 
| 51 36 |  | 
| 52 | 
            -
                  def decrement_counters | 
| 37 | 
            +
                  def decrement_counters
         | 
| 53 38 | 
             
                    update_counters(-1)
         | 
| 54 39 | 
             
                  end
         | 
| 55 40 |  | 
| 56 | 
            -
                  def increment_counters | 
| 41 | 
            +
                  def increment_counters
         | 
| 57 42 | 
             
                    update_counters(1)
         | 
| 58 43 | 
             
                  end
         | 
| 59 44 |  | 
| 45 | 
            +
                  def decrement_counters_before_last_save
         | 
| 46 | 
            +
                    if reflection.polymorphic?
         | 
| 47 | 
            +
                      model_was = owner.attribute_before_last_save(reflection.foreign_type).try(:constantize)
         | 
| 48 | 
            +
                    else
         | 
| 49 | 
            +
                      model_was = klass
         | 
| 50 | 
            +
                    end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                    foreign_key_was = owner.attribute_before_last_save(reflection.foreign_key)
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                    if foreign_key_was && model_was < ActiveRecord::Base
         | 
| 55 | 
            +
                      update_counters_via_scope(model_was, foreign_key_was, -1)
         | 
| 56 | 
            +
                    end
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
             | 
| 60 59 | 
             
                  def target_changed?
         | 
| 61 60 | 
             
                    owner.saved_change_to_attribute?(reflection.foreign_key)
         | 
| 62 61 | 
             
                  end
         | 
| 63 62 |  | 
| 64 63 | 
             
                  private
         | 
| 64 | 
            +
                    def replace(record)
         | 
| 65 | 
            +
                      if record
         | 
| 66 | 
            +
                        raise_on_type_mismatch!(record)
         | 
| 67 | 
            +
                        set_inverse_instance(record)
         | 
| 68 | 
            +
                        @updated = true
         | 
| 69 | 
            +
                      end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                      replace_keys(record)
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                      self.target = record
         | 
| 74 | 
            +
                    end
         | 
| 65 75 |  | 
| 66 76 | 
             
                    def update_counters(by)
         | 
| 67 77 | 
             
                      if require_counter_update? && foreign_key_present?
         | 
| 68 78 | 
             
                        if target && !stale_target?
         | 
| 69 79 | 
             
                          target.increment!(reflection.counter_cache_column, by, touch: reflection.options[:touch])
         | 
| 70 80 | 
             
                        else
         | 
| 71 | 
            -
                          klass. | 
| 81 | 
            +
                          update_counters_via_scope(klass, owner._read_attribute(reflection.foreign_key), by)
         | 
| 72 82 | 
             
                        end
         | 
| 73 83 | 
             
                      end
         | 
| 74 84 | 
             
                    end
         | 
| 75 85 |  | 
| 86 | 
            +
                    def update_counters_via_scope(klass, foreign_key, by)
         | 
| 87 | 
            +
                      scope = klass.unscoped.where!(primary_key(klass) => foreign_key)
         | 
| 88 | 
            +
                      scope.update_counters(reflection.counter_cache_column => by, touch: reflection.options[:touch])
         | 
| 89 | 
            +
                    end
         | 
| 90 | 
            +
             | 
| 76 91 | 
             
                    def find_target?
         | 
| 77 92 | 
             
                      !loaded? && foreign_key_present? && klass
         | 
| 78 93 | 
             
                    end
         | 
| @@ -81,25 +96,12 @@ module ActiveRecord | |
| 81 96 | 
             
                      reflection.counter_cache_column && owner.persisted?
         | 
| 82 97 | 
             
                    end
         | 
| 83 98 |  | 
| 84 | 
            -
                    def update_counters_on_replace(record)
         | 
| 85 | 
            -
                      if require_counter_update? && different_target?(record)
         | 
| 86 | 
            -
                        owner.instance_variable_set :@_after_replace_counter_called, true
         | 
| 87 | 
            -
                        record.increment!(reflection.counter_cache_column, touch: reflection.options[:touch])
         | 
| 88 | 
            -
                        decrement_counters
         | 
| 89 | 
            -
                      end
         | 
| 90 | 
            -
                    end
         | 
| 91 | 
            -
             | 
| 92 | 
            -
                    # Checks whether record is different to the current target, without loading it
         | 
| 93 | 
            -
                    def different_target?(record)
         | 
| 94 | 
            -
                      record._read_attribute(primary_key(record)) != owner._read_attribute(reflection.foreign_key)
         | 
| 95 | 
            -
                    end
         | 
| 96 | 
            -
             | 
| 97 99 | 
             
                    def replace_keys(record)
         | 
| 98 | 
            -
                      owner[reflection.foreign_key] = record ? record._read_attribute(primary_key(record)) : nil
         | 
| 100 | 
            +
                      owner[reflection.foreign_key] = record ? record._read_attribute(primary_key(record.class)) : nil
         | 
| 99 101 | 
             
                    end
         | 
| 100 102 |  | 
| 101 | 
            -
                    def primary_key( | 
| 102 | 
            -
                      reflection.association_primary_key( | 
| 103 | 
            +
                    def primary_key(klass)
         | 
| 104 | 
            +
                      reflection.association_primary_key(klass)
         | 
| 103 105 | 
             
                    end
         | 
| 104 106 |  | 
| 105 107 | 
             
                    def foreign_key_present?
         | 
| @@ -113,14 +115,6 @@ module ActiveRecord | |
| 113 115 | 
             
                      inverse && inverse.has_one?
         | 
| 114 116 | 
             
                    end
         | 
| 115 117 |  | 
| 116 | 
            -
                    def target_id
         | 
| 117 | 
            -
                      if options[:primary_key]
         | 
| 118 | 
            -
                        owner.send(reflection.name).try(:id)
         | 
| 119 | 
            -
                      else
         | 
| 120 | 
            -
                        owner._read_attribute(reflection.foreign_key)
         | 
| 121 | 
            -
                      end
         | 
| 122 | 
            -
                    end
         | 
| 123 | 
            -
             | 
| 124 118 | 
             
                    def stale_state
         | 
| 125 119 | 
             
                      result = owner._read_attribute(reflection.foreign_key) { |n| owner.send(:missing_attribute, n, caller) }
         | 
| 126 120 | 
             
                      result && result.to_s
         |