activerecord 5.1.7 → 5.2.0.beta1
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 +5 -5
- data/CHANGELOG.md +221 -900
- data/README.rdoc +3 -3
- data/examples/performance.rb +2 -0
- data/examples/simple.rb +2 -0
- data/lib/active_record.rb +10 -3
- data/lib/active_record/aggregations.rb +2 -0
- data/lib/active_record/association_relation.rb +2 -0
- data/lib/active_record/associations.rb +13 -42
- data/lib/active_record/associations/alias_tracker.rb +17 -17
- data/lib/active_record/associations/association.rb +11 -22
- data/lib/active_record/associations/association_scope.rb +32 -44
- data/lib/active_record/associations/belongs_to_association.rb +6 -4
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -1
- data/lib/active_record/associations/builder/association.rb +2 -5
- data/lib/active_record/associations/builder/belongs_to.rb +7 -12
- 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 +41 -33
- data/lib/active_record/associations/collection_proxy.rb +11 -14
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +4 -2
- data/lib/active_record/associations/has_many_through_association.rb +4 -2
- data/lib/active_record/associations/has_one_association.rb +3 -1
- data/lib/active_record/associations/has_one_through_association.rb +3 -1
- data/lib/active_record/associations/join_dependency.rb +22 -40
- data/lib/active_record/associations/join_dependency/join_association.rb +17 -56
- data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -9
- data/lib/active_record/associations/preloader.rb +17 -37
- data/lib/active_record/associations/preloader/association.rb +42 -58
- data/lib/active_record/associations/preloader/through_association.rb +71 -79
- data/lib/active_record/associations/singular_association.rb +14 -10
- data/lib/active_record/associations/through_association.rb +3 -1
- data/lib/active_record/attribute_assignment.rb +2 -0
- data/lib/active_record/attribute_decorators.rb +3 -2
- data/lib/active_record/attribute_methods.rb +47 -7
- 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 +8 -2
- 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/attributes.rb +7 -6
- data/lib/active_record/autosave_association.rb +5 -11
- data/lib/active_record/base.rb +2 -0
- data/lib/active_record/callbacks.rb +6 -8
- 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 +10 -5
- 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 +120 -28
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +7 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +14 -33
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +13 -5
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +40 -2
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +103 -63
- data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
- data/lib/active_record/connection_adapters/abstract_adapter.rb +62 -90
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +75 -138
- 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 +3 -1
- 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 -6
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -30
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +91 -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.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -11
- 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_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 +3 -5
- 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/quoting.rb +10 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +11 -7
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +79 -65
- 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 +47 -82
- data/lib/active_record/connection_adapters/schema_cache.rb +2 -0
- 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 +19 -2
- 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 +71 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +34 -89
- 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 +27 -57
- data/lib/active_record/counter_cache.rb +15 -12
- data/lib/active_record/define_callbacks.rb +5 -3
- data/lib/active_record/dynamic_matchers.rb +9 -9
- data/lib/active_record/enum.rb +15 -13
- data/lib/active_record/errors.rb +54 -21
- 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 +40 -24
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +6 -5
- 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 +31 -20
- data/lib/active_record/locking/pessimistic.rb +10 -7
- data/lib/active_record/log_subscriber.rb +2 -0
- data/lib/active_record/migration.rb +47 -21
- data/lib/active_record/migration/command_recorder.rb +11 -9
- data/lib/active_record/migration/compatibility.rb +20 -2
- data/lib/active_record/migration/join_table.rb +2 -0
- data/lib/active_record/model_schema.rb +29 -38
- 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 +184 -40
- data/lib/active_record/query_cache.rb +17 -12
- data/lib/active_record/querying.rb +3 -1
- data/lib/active_record/railtie.rb +54 -1
- 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 +41 -28
- data/lib/active_record/readonly_attributes.rb +3 -2
- data/lib/active_record/reflection.rb +100 -182
- data/lib/active_record/relation.rb +61 -193
- data/lib/active_record/relation/batches.rb +20 -5
- data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
- data/lib/active_record/relation/calculations.rb +40 -23
- data/lib/active_record/relation/delegation.rb +10 -27
- data/lib/active_record/relation/finder_methods.rb +53 -49
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +22 -19
- data/lib/active_record/relation/predicate_builder.rb +42 -79
- 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 +54 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/query_attribute.rb +9 -2
- data/lib/active_record/relation/query_methods.rb +80 -69
- data/lib/active_record/relation/record_fetch_warning.rb +2 -0
- data/lib/active_record/relation/spawn_methods.rb +2 -0
- data/lib/active_record/relation/where_clause.rb +50 -67
- data/lib/active_record/relation/where_clause_factory.rb +4 -46
- data/lib/active_record/result.rb +2 -0
- data/lib/active_record/runtime_registry.rb +2 -0
- data/lib/active_record/sanitization.rb +15 -9
- data/lib/active_record/schema.rb +3 -1
- data/lib/active_record/schema_dumper.rb +24 -23
- data/lib/active_record/schema_migration.rb +2 -0
- data/lib/active_record/scoping.rb +9 -8
- data/lib/active_record/scoping/default.rb +6 -7
- data/lib/active_record/scoping/named.rb +15 -7
- 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 +2 -0
- data/lib/active_record/suppressor.rb +2 -0
- data/lib/active_record/table_metadata.rb +3 -1
- data/lib/active_record/tasks/database_tasks.rb +23 -12
- 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 +5 -12
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +9 -7
- data/lib/active_record/translation.rb +2 -0
- data/lib/active_record/type.rb +4 -1
- 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 +2 -4
- 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_caster.rb +2 -0
- data/lib/active_record/type_caster/connection.rb +2 -0
- data/lib/active_record/type_caster/map.rb +2 -0
- data/lib/active_record/validations.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/version.rb +2 -0
- data/lib/rails/generators/active_record.rb +3 -1
- 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.rb +2 -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/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
- metadata +25 -38
- 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.rb +0 -240
- data/lib/active_record/attribute/user_provided_default.rb +0 -30
- data/lib/active_record/attribute_mutation_tracker.rb +0 -122
- data/lib/active_record/attribute_set.rb +0 -113
- data/lib/active_record/attribute_set/builder.rb +0 -126
- data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
- 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,3 +1,5 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            require "active_record/associations/join_dependency/join_part"
         | 
| 2 4 |  | 
| 3 5 | 
             
            module ActiveRecord
         | 
| @@ -9,11 +11,12 @@ module ActiveRecord | |
| 9 11 |  | 
| 10 12 | 
             
                    attr_accessor :tables
         | 
| 11 13 |  | 
| 12 | 
            -
                    def initialize(reflection, children)
         | 
| 14 | 
            +
                    def initialize(reflection, children, alias_tracker)
         | 
| 13 15 | 
             
                      super(reflection.klass, children)
         | 
| 14 16 |  | 
| 15 | 
            -
                      @ | 
| 16 | 
            -
                      @ | 
| 17 | 
            +
                      @alias_tracker = alias_tracker
         | 
| 18 | 
            +
                      @reflection    = reflection
         | 
| 19 | 
            +
                      @tables        = nil
         | 
| 17 20 | 
             
                    end
         | 
| 18 21 |  | 
| 19 22 | 
             
                    def match?(other)
         | 
| @@ -21,11 +24,8 @@ module ActiveRecord | |
| 21 24 | 
             
                      super && reflection == other.reflection
         | 
| 22 25 | 
             
                    end
         | 
| 23 26 |  | 
| 24 | 
            -
                    JoinInformation = Struct.new :joins, :binds
         | 
| 25 | 
            -
             | 
| 26 27 | 
             
                    def join_constraints(foreign_table, foreign_klass, join_type, tables, chain)
         | 
| 27 28 | 
             
                      joins         = []
         | 
| 28 | 
            -
                      binds         = []
         | 
| 29 29 | 
             
                      tables        = tables.reverse
         | 
| 30 30 |  | 
| 31 31 | 
             
                      # The chain starts with the target table, but we want to end with it here (makes
         | 
| @@ -34,71 +34,32 @@ module ActiveRecord | |
| 34 34 | 
             
                        table = tables.shift
         | 
| 35 35 | 
             
                        klass = reflection.klass
         | 
| 36 36 |  | 
| 37 | 
            -
                         | 
| 38 | 
            -
                        key         = join_keys.key
         | 
| 39 | 
            -
                        foreign_key = join_keys.foreign_key
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                        constraint = build_constraint(klass, table, key, foreign_table, foreign_key)
         | 
| 42 | 
            -
             | 
| 43 | 
            -
                        rel = reflection.join_scope(table)
         | 
| 37 | 
            +
                        constraint = reflection.build_join_constraint(table, foreign_table)
         | 
| 44 38 |  | 
| 45 | 
            -
                         | 
| 46 | 
            -
                          binds += rel.bound_attributes
         | 
| 47 | 
            -
                          constraint = constraint.and rel.arel.constraints
         | 
| 48 | 
            -
                        end
         | 
| 39 | 
            +
                        joins << table.create_join(table, table.create_on(constraint), join_type)
         | 
| 49 40 |  | 
| 50 | 
            -
                         | 
| 51 | 
            -
             | 
| 52 | 
            -
                          column = klass.columns_hash[reflection.type.to_s]
         | 
| 41 | 
            +
                        join_scope = reflection.join_scope(table, foreign_klass)
         | 
| 42 | 
            +
                        arel = join_scope.arel(alias_tracker.aliases)
         | 
| 53 43 |  | 
| 54 | 
            -
             | 
| 55 | 
            -
                           | 
| 44 | 
            +
                        if arel.constraints.any?
         | 
| 45 | 
            +
                          joins.concat arel.join_sources
         | 
| 46 | 
            +
                          right = joins.last.right
         | 
| 47 | 
            +
                          right.expr = right.expr.and(arel.constraints)
         | 
| 56 48 | 
             
                        end
         | 
| 57 49 |  | 
| 58 | 
            -
                        joins << table.create_join(table, table.create_on(constraint), join_type)
         | 
| 59 | 
            -
             | 
| 60 50 | 
             
                        # The current table in this iteration becomes the foreign table in the next
         | 
| 61 51 | 
             
                        foreign_table, foreign_klass = table, klass
         | 
| 62 52 | 
             
                      end
         | 
| 63 53 |  | 
| 64 | 
            -
                       | 
| 65 | 
            -
                    end
         | 
| 66 | 
            -
             | 
| 67 | 
            -
                    #  Builds equality condition.
         | 
| 68 | 
            -
                    #
         | 
| 69 | 
            -
                    #  Example:
         | 
| 70 | 
            -
                    #
         | 
| 71 | 
            -
                    #  class Physician < ActiveRecord::Base
         | 
| 72 | 
            -
                    #    has_many :appointments
         | 
| 73 | 
            -
                    #  end
         | 
| 74 | 
            -
                    #
         | 
| 75 | 
            -
                    #  If I execute `Physician.joins(:appointments).to_a` then
         | 
| 76 | 
            -
                    #    klass         # => Physician
         | 
| 77 | 
            -
                    #    table         # => #<Arel::Table @name="appointments" ...>
         | 
| 78 | 
            -
                    #    key           # =>  physician_id
         | 
| 79 | 
            -
                    #    foreign_table # => #<Arel::Table @name="physicians" ...>
         | 
| 80 | 
            -
                    #    foreign_key   # => id
         | 
| 81 | 
            -
                    #
         | 
| 82 | 
            -
                    def build_constraint(klass, table, key, foreign_table, foreign_key)
         | 
| 83 | 
            -
                      constraint = table[key].eq(foreign_table[foreign_key])
         | 
| 84 | 
            -
             | 
| 85 | 
            -
                      if klass.finder_needs_type_condition?
         | 
| 86 | 
            -
                        constraint = table.create_and([
         | 
| 87 | 
            -
                          constraint,
         | 
| 88 | 
            -
                          klass.send(:type_condition, table)
         | 
| 89 | 
            -
                        ])
         | 
| 90 | 
            -
                      end
         | 
| 91 | 
            -
             | 
| 92 | 
            -
                      constraint
         | 
| 54 | 
            +
                      joins
         | 
| 93 55 | 
             
                    end
         | 
| 94 56 |  | 
| 95 57 | 
             
                    def table
         | 
| 96 58 | 
             
                      tables.first
         | 
| 97 59 | 
             
                    end
         | 
| 98 60 |  | 
| 99 | 
            -
                     | 
| 100 | 
            -
                       | 
| 101 | 
            -
                    end
         | 
| 61 | 
            +
                    protected
         | 
| 62 | 
            +
                      attr_reader :alias_tracker
         | 
| 102 63 | 
             
                  end
         | 
| 103 64 | 
             
                end
         | 
| 104 65 | 
             
              end
         | 
| @@ -1,20 +1,21 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            require "active_record/associations/join_dependency/join_part"
         | 
| 2 4 |  | 
| 3 5 | 
             
            module ActiveRecord
         | 
| 4 6 | 
             
              module Associations
         | 
| 5 7 | 
             
                class JoinDependency # :nodoc:
         | 
| 6 8 | 
             
                  class JoinBase < JoinPart # :nodoc:
         | 
| 7 | 
            -
                     | 
| 8 | 
            -
                      return true if self == other
         | 
| 9 | 
            -
                      super && base_klass == other.base_klass
         | 
| 10 | 
            -
                    end
         | 
| 9 | 
            +
                    attr_reader :table
         | 
| 11 10 |  | 
| 12 | 
            -
                    def table
         | 
| 13 | 
            -
                      base_klass | 
| 11 | 
            +
                    def initialize(base_klass, table, children)
         | 
| 12 | 
            +
                      super(base_klass, children)
         | 
| 13 | 
            +
                      @table = table
         | 
| 14 14 | 
             
                    end
         | 
| 15 15 |  | 
| 16 | 
            -
                    def  | 
| 17 | 
            -
                       | 
| 16 | 
            +
                    def match?(other)
         | 
| 17 | 
            +
                      return true if self == other
         | 
| 18 | 
            +
                      super && base_klass == other.base_klass
         | 
| 18 19 | 
             
                    end
         | 
| 19 20 | 
             
                  end
         | 
| 20 21 | 
             
                end
         | 
| @@ -1,3 +1,5 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            module ActiveRecord
         | 
| 2 4 | 
             
              module Associations
         | 
| 3 5 | 
             
                class JoinDependency # :nodoc:
         | 
| @@ -22,10 +24,6 @@ module ActiveRecord | |
| 22 24 | 
             
                      @children = children
         | 
| 23 25 | 
             
                    end
         | 
| 24 26 |  | 
| 25 | 
            -
                    def name
         | 
| 26 | 
            -
                      reflection.name
         | 
| 27 | 
            -
                    end
         | 
| 28 | 
            -
             | 
| 29 27 | 
             
                    def match?(other)
         | 
| 30 28 | 
             
                      self.class == other.class
         | 
| 31 29 | 
             
                    end
         | 
| @@ -40,11 +38,6 @@ module ActiveRecord | |
| 40 38 | 
             
                      raise NotImplementedError
         | 
| 41 39 | 
             
                    end
         | 
| 42 40 |  | 
| 43 | 
            -
                    # The alias for the active_record's table
         | 
| 44 | 
            -
                    def aliased_table_name
         | 
| 45 | 
            -
                      raise NotImplementedError
         | 
| 46 | 
            -
                    end
         | 
| 47 | 
            -
             | 
| 48 41 | 
             
                    def extract_record(row, column_names_with_alias)
         | 
| 49 42 | 
             
                      # This code is performance critical as it is called per row.
         | 
| 50 43 | 
             
                      # see: https://github.com/rails/rails/pull/12185
         | 
| @@ -1,3 +1,5 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            module ActiveRecord
         | 
| 2 4 | 
             
              module Associations
         | 
| 3 5 | 
             
                # Implements the details of eager loading of Active Record associations.
         | 
| @@ -42,20 +44,10 @@ module ActiveRecord | |
| 42 44 | 
             
                  extend ActiveSupport::Autoload
         | 
| 43 45 |  | 
| 44 46 | 
             
                  eager_autoload do
         | 
| 45 | 
            -
                    autoload :Association, | 
| 46 | 
            -
                    autoload : | 
| 47 | 
            -
                    autoload :CollectionAssociation, "active_record/associations/preloader/collection_association"
         | 
| 48 | 
            -
                    autoload :ThroughAssociation,    "active_record/associations/preloader/through_association"
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                    autoload :HasMany,             "active_record/associations/preloader/has_many"
         | 
| 51 | 
            -
                    autoload :HasManyThrough,      "active_record/associations/preloader/has_many_through"
         | 
| 52 | 
            -
                    autoload :HasOne,              "active_record/associations/preloader/has_one"
         | 
| 53 | 
            -
                    autoload :HasOneThrough,       "active_record/associations/preloader/has_one_through"
         | 
| 54 | 
            -
                    autoload :BelongsTo,           "active_record/associations/preloader/belongs_to"
         | 
| 47 | 
            +
                    autoload :Association,        "active_record/associations/preloader/association"
         | 
| 48 | 
            +
                    autoload :ThroughAssociation, "active_record/associations/preloader/through_association"
         | 
| 55 49 | 
             
                  end
         | 
| 56 50 |  | 
| 57 | 
            -
                  NULL_RELATION = Struct.new(:values, :where_clause, :joins_values).new({}, Relation::WhereClause.empty, [])
         | 
| 58 | 
            -
             | 
| 59 51 | 
             
                  # Eager loads the named associations for the given Active Record record(s).
         | 
| 60 52 | 
             
                  #
         | 
| 61 53 | 
             
                  # In this description, 'association name' shall refer to the name passed
         | 
| @@ -91,14 +83,13 @@ module ActiveRecord | |
| 91 83 | 
             
                  #   { author: :avatar }
         | 
| 92 84 | 
             
                  #   [ :books, { author: :avatar } ]
         | 
| 93 85 | 
             
                  def preload(records, associations, preload_scope = nil)
         | 
| 94 | 
            -
                    records | 
| 95 | 
            -
                    associations  = Array.wrap(associations)
         | 
| 96 | 
            -
                    preload_scope = preload_scope || NULL_RELATION
         | 
| 86 | 
            +
                    records = records.compact
         | 
| 97 87 |  | 
| 98 88 | 
             
                    if records.empty?
         | 
| 99 89 | 
             
                      []
         | 
| 100 90 | 
             
                    else
         | 
| 101 | 
            -
                       | 
| 91 | 
            +
                      records.uniq!
         | 
| 92 | 
            +
                      Array.wrap(associations).flat_map { |association|
         | 
| 102 93 | 
             
                        preloaders_on association, records, preload_scope
         | 
| 103 94 | 
             
                      }
         | 
| 104 95 | 
             
                    end
         | 
| @@ -147,7 +138,7 @@ module ActiveRecord | |
| 147 138 | 
             
                    def preloaders_for_one(association, records, scope)
         | 
| 148 139 | 
             
                      grouped_records(association, records).flat_map do |reflection, klasses|
         | 
| 149 140 | 
             
                        klasses.map do |rhs_klass, rs|
         | 
| 150 | 
            -
                          loader = preloader_for(reflection, rs | 
| 141 | 
            +
                          loader = preloader_for(reflection, rs).new(rhs_klass, rs, reflection, scope)
         | 
| 151 142 | 
             
                          loader.run self
         | 
| 152 143 | 
             
                          loader
         | 
| 153 144 | 
             
                        end
         | 
| @@ -159,6 +150,7 @@ module ActiveRecord | |
| 159 150 | 
             
                      records.each do |record|
         | 
| 160 151 | 
             
                        next unless record
         | 
| 161 152 | 
             
                        assoc = record.association(association)
         | 
| 153 | 
            +
                        next unless assoc.klass
         | 
| 162 154 | 
             
                        klasses = h[assoc.reflection] ||= {}
         | 
| 163 155 | 
             
                        (klasses[assoc.klass] ||= []) << record
         | 
| 164 156 | 
             
                      end
         | 
| @@ -166,8 +158,6 @@ module ActiveRecord | |
| 166 158 | 
             
                    end
         | 
| 167 159 |  | 
| 168 160 | 
             
                    class AlreadyLoaded # :nodoc:
         | 
| 169 | 
            -
                      attr_reader :owners, :reflection
         | 
| 170 | 
            -
             | 
| 171 161 | 
             
                      def initialize(klass, owners, reflection, preload_scope)
         | 
| 172 162 | 
             
                        @owners = owners
         | 
| 173 163 | 
             
                        @reflection = reflection
         | 
| @@ -178,34 +168,24 @@ module ActiveRecord | |
| 178 168 | 
             
                      def preloaded_records
         | 
| 179 169 | 
             
                        owners.flat_map { |owner| owner.association(reflection.name).target }
         | 
| 180 170 | 
             
                      end
         | 
| 181 | 
            -
                    end
         | 
| 182 171 |  | 
| 183 | 
            -
             | 
| 184 | 
            -
             | 
| 185 | 
            -
                      def self.run(preloader); end
         | 
| 186 | 
            -
                      def self.preloaded_records; []; end
         | 
| 187 | 
            -
                      def self.owners; []; end
         | 
| 172 | 
            +
                      protected
         | 
| 173 | 
            +
                        attr_reader :owners, :reflection
         | 
| 188 174 | 
             
                    end
         | 
| 189 175 |  | 
| 190 176 | 
             
                    # Returns a class containing the logic needed to load preload the data
         | 
| 191 | 
            -
                    # and attach it to a relation.  | 
| 192 | 
            -
                    # +Preloader::HasManyThrough+. The class returned implements a `run` method
         | 
| 177 | 
            +
                    # and attach it to a relation. The class returned implements a `run` method
         | 
| 193 178 | 
             
                    # that accepts a preloader.
         | 
| 194 | 
            -
                    def preloader_for(reflection, owners | 
| 195 | 
            -
                      return NullPreloader unless rhs_klass
         | 
| 196 | 
            -
             | 
| 179 | 
            +
                    def preloader_for(reflection, owners)
         | 
| 197 180 | 
             
                      if owners.first.association(reflection.name).loaded?
         | 
| 198 181 | 
             
                        return AlreadyLoaded
         | 
| 199 182 | 
             
                      end
         | 
| 200 183 | 
             
                      reflection.check_preloadable!
         | 
| 201 184 |  | 
| 202 | 
            -
                       | 
| 203 | 
            -
             | 
| 204 | 
            -
             | 
| 205 | 
            -
             | 
| 206 | 
            -
                        reflection.options[:through] ? HasOneThrough : HasOne
         | 
| 207 | 
            -
                      when :belongs_to
         | 
| 208 | 
            -
                        BelongsTo
         | 
| 185 | 
            +
                      if reflection.options[:through]
         | 
| 186 | 
            +
                        ThroughAssociation
         | 
| 187 | 
            +
                      else
         | 
| 188 | 
            +
                        Association
         | 
| 209 189 | 
             
                      end
         | 
| 210 190 | 
             
                    end
         | 
| 211 191 | 
             
                end
         | 
| @@ -1,8 +1,9 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            module ActiveRecord
         | 
| 2 4 | 
             
              module Associations
         | 
| 3 5 | 
             
                class Preloader
         | 
| 4 6 | 
             
                  class Association #:nodoc:
         | 
| 5 | 
            -
                    attr_reader :owners, :reflection, :preload_scope, :model, :klass
         | 
| 6 7 | 
             
                    attr_reader :preloaded_records
         | 
| 7 8 |  | 
| 8 9 | 
             
                    def initialize(klass, owners, reflection, preload_scope)
         | 
| @@ -11,79 +12,54 @@ module ActiveRecord | |
| 11 12 | 
             
                      @reflection    = reflection
         | 
| 12 13 | 
             
                      @preload_scope = preload_scope
         | 
| 13 14 | 
             
                      @model         = owners.first && owners.first.class
         | 
| 14 | 
            -
                      @scope         = nil
         | 
| 15 15 | 
             
                      @preloaded_records = []
         | 
| 16 16 | 
             
                    end
         | 
| 17 17 |  | 
| 18 18 | 
             
                    def run(preloader)
         | 
| 19 | 
            -
                       | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
                       | 
| 24 | 
            -
                    end
         | 
| 25 | 
            -
             | 
| 26 | 
            -
                    def scope
         | 
| 27 | 
            -
                      @scope ||= build_scope
         | 
| 28 | 
            -
                    end
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                    def records_for(ids)
         | 
| 31 | 
            -
                      scope.where(association_key_name => ids)
         | 
| 32 | 
            -
                    end
         | 
| 33 | 
            -
             | 
| 34 | 
            -
                    def table
         | 
| 35 | 
            -
                      klass.arel_table
         | 
| 36 | 
            -
                    end
         | 
| 37 | 
            -
             | 
| 38 | 
            -
                    # The name of the key on the associated records
         | 
| 39 | 
            -
                    def association_key_name
         | 
| 40 | 
            -
                      raise NotImplementedError
         | 
| 41 | 
            -
                    end
         | 
| 42 | 
            -
             | 
| 43 | 
            -
                    # This is overridden by HABTM as the condition should be on the foreign_key column in
         | 
| 44 | 
            -
                    # the join table
         | 
| 45 | 
            -
                    def association_key
         | 
| 46 | 
            -
                      klass.arel_attribute(association_key_name, table)
         | 
| 47 | 
            -
                    end
         | 
| 19 | 
            +
                      records = load_records do |record|
         | 
| 20 | 
            +
                        owner = owners_by_key[convert_key(record[association_key_name])]
         | 
| 21 | 
            +
                        association = owner.association(reflection.name)
         | 
| 22 | 
            +
                        association.set_inverse_instance(record)
         | 
| 23 | 
            +
                      end
         | 
| 48 24 |  | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
                       | 
| 25 | 
            +
                      owners.each do |owner|
         | 
| 26 | 
            +
                        associate_records_to_owner(owner, records[convert_key(owner[owner_key_name])] || [])
         | 
| 27 | 
            +
                      end
         | 
| 52 28 | 
             
                    end
         | 
| 53 29 |  | 
| 54 | 
            -
                     | 
| 55 | 
            -
                      reflection | 
| 56 | 
            -
                    end
         | 
| 30 | 
            +
                    protected
         | 
| 31 | 
            +
                      attr_reader :owners, :reflection, :preload_scope, :model, :klass
         | 
| 57 32 |  | 
| 58 33 | 
             
                    private
         | 
| 34 | 
            +
                      # The name of the key on the associated records
         | 
| 35 | 
            +
                      def association_key_name
         | 
| 36 | 
            +
                        reflection.join_primary_key(klass)
         | 
| 37 | 
            +
                      end
         | 
| 59 38 |  | 
| 60 | 
            -
                       | 
| 61 | 
            -
             | 
| 62 | 
            -
             | 
| 63 | 
            -
             | 
| 64 | 
            -
                          association.set_inverse_instance(record)
         | 
| 65 | 
            -
                        end
         | 
| 39 | 
            +
                      # The name of the key on the model which declares the association
         | 
| 40 | 
            +
                      def owner_key_name
         | 
| 41 | 
            +
                        reflection.join_foreign_key
         | 
| 42 | 
            +
                      end
         | 
| 66 43 |  | 
| 67 | 
            -
             | 
| 68 | 
            -
             | 
| 44 | 
            +
                      def associate_records_to_owner(owner, records)
         | 
| 45 | 
            +
                        association = owner.association(reflection.name)
         | 
| 46 | 
            +
                        if reflection.collection?
         | 
| 47 | 
            +
                          association.loaded!
         | 
| 48 | 
            +
                          association.target.concat(records)
         | 
| 49 | 
            +
                        else
         | 
| 50 | 
            +
                          association.target = records.first
         | 
| 69 51 | 
             
                        end
         | 
| 70 52 | 
             
                      end
         | 
| 71 53 |  | 
| 72 54 | 
             
                      def owner_keys
         | 
| 73 | 
            -
                         | 
| 74 | 
            -
                          @owner_keys = owners.map do |owner|
         | 
| 75 | 
            -
                            owner[owner_key_name]
         | 
| 76 | 
            -
                          end
         | 
| 77 | 
            -
                          @owner_keys.uniq!
         | 
| 78 | 
            -
                          @owner_keys.compact!
         | 
| 79 | 
            -
                        end
         | 
| 80 | 
            -
                        @owner_keys
         | 
| 55 | 
            +
                        @owner_keys ||= owners_by_key.keys
         | 
| 81 56 | 
             
                      end
         | 
| 82 57 |  | 
| 83 58 | 
             
                      def owners_by_key
         | 
| 84 59 | 
             
                        unless defined?(@owners_by_key)
         | 
| 85 60 | 
             
                          @owners_by_key = owners.each_with_object({}) do |owner, h|
         | 
| 86 | 
            -
                             | 
| 61 | 
            +
                            key = convert_key(owner[owner_key_name])
         | 
| 62 | 
            +
                            h[key] = owner if key
         | 
| 87 63 | 
             
                          end
         | 
| 88 64 | 
             
                        end
         | 
| 89 65 | 
             
                        @owners_by_key
         | 
| @@ -119,15 +95,23 @@ module ActiveRecord | |
| 119 95 | 
             
                        # Make several smaller queries if necessary or make one query if the adapter supports it
         | 
| 120 96 | 
             
                        slices = owner_keys.each_slice(klass.connection.in_clause_length || owner_keys.size)
         | 
| 121 97 | 
             
                        @preloaded_records = slices.flat_map do |slice|
         | 
| 122 | 
            -
                          records_for(slice | 
| 98 | 
            +
                          records_for(slice, &block)
         | 
| 123 99 | 
             
                        end
         | 
| 124 100 | 
             
                        @preloaded_records.group_by do |record|
         | 
| 125 101 | 
             
                          convert_key(record[association_key_name])
         | 
| 126 102 | 
             
                        end
         | 
| 127 103 | 
             
                      end
         | 
| 128 104 |  | 
| 105 | 
            +
                      def records_for(ids, &block)
         | 
| 106 | 
            +
                        scope.where(association_key_name => ids).load(&block)
         | 
| 107 | 
            +
                      end
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                      def scope
         | 
| 110 | 
            +
                        @scope ||= build_scope
         | 
| 111 | 
            +
                      end
         | 
| 112 | 
            +
             | 
| 129 113 | 
             
                      def reflection_scope
         | 
| 130 | 
            -
                        @reflection_scope ||= reflection.scope_for(klass)
         | 
| 114 | 
            +
                        @reflection_scope ||= reflection.scope ? reflection.scope_for(klass.unscoped) : klass.unscoped
         | 
| 131 115 | 
             
                      end
         | 
| 132 116 |  | 
| 133 117 | 
             
                      def build_scope
         | 
| @@ -137,8 +121,8 @@ module ActiveRecord | |
| 137 121 | 
             
                          scope.where!(reflection.type => model.base_class.sti_name)
         | 
| 138 122 | 
             
                        end
         | 
| 139 123 |  | 
| 140 | 
            -
                        scope.merge!(reflection_scope)
         | 
| 141 | 
            -
                        scope.merge!(preload_scope) if preload_scope | 
| 124 | 
            +
                        scope.merge!(reflection_scope) if reflection.scope
         | 
| 125 | 
            +
                        scope.merge!(preload_scope) if preload_scope
         | 
| 142 126 | 
             
                        scope
         | 
| 143 127 | 
             
                      end
         | 
| 144 128 | 
             
                  end
         | 
| @@ -1,113 +1,105 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            module ActiveRecord
         | 
| 2 4 | 
             
              module Associations
         | 
| 3 5 | 
             
                class Preloader
         | 
| 4 | 
            -
                   | 
| 5 | 
            -
                    def  | 
| 6 | 
            -
                       | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
                       | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
                    def associated_records_by_owner(preloader)
         | 
| 14 | 
            -
                      preloader.preload(owners,
         | 
| 15 | 
            -
                                        through_reflection.name,
         | 
| 16 | 
            -
                                        through_scope)
         | 
| 17 | 
            -
             | 
| 18 | 
            -
                      through_records = owners.map do |owner|
         | 
| 19 | 
            -
                        association = owner.association through_reflection.name
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                        center = target_records_from_association(association)
         | 
| 22 | 
            -
                        [owner, Array(center)]
         | 
| 23 | 
            -
                      end
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                      reset_association owners, through_reflection.name
         | 
| 26 | 
            -
             | 
| 27 | 
            -
                      middle_records = through_records.flat_map { |(_, rec)| rec }
         | 
| 28 | 
            -
             | 
| 29 | 
            -
                      preloaders = preloader.preload(middle_records,
         | 
| 30 | 
            -
                                                     source_reflection.name,
         | 
| 31 | 
            -
                                                     reflection_scope)
         | 
| 32 | 
            -
             | 
| 6 | 
            +
                  class ThroughAssociation < Association # :nodoc:
         | 
| 7 | 
            +
                    def run(preloader)
         | 
| 8 | 
            +
                      already_loaded     = owners.first.association(through_reflection.name).loaded?
         | 
| 9 | 
            +
                      through_scope      = through_scope()
         | 
| 10 | 
            +
                      reflection_scope   = target_reflection_scope
         | 
| 11 | 
            +
                      through_preloaders = preloader.preload(owners, through_reflection.name, through_scope)
         | 
| 12 | 
            +
                      middle_records     = through_preloaders.flat_map(&:preloaded_records)
         | 
| 13 | 
            +
                      preloaders         = preloader.preload(middle_records, source_reflection.name, reflection_scope)
         | 
| 33 14 | 
             
                      @preloaded_records = preloaders.flat_map(&:preloaded_records)
         | 
| 34 15 |  | 
| 35 | 
            -
                       | 
| 36 | 
            -
                         | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
                        pl_to_middle = center.group_by { |record| middle_to_pl[record] }
         | 
| 43 | 
            -
             | 
| 44 | 
            -
                        records_by_owner[lhs] = pl_to_middle.flat_map do |pl, middles|
         | 
| 45 | 
            -
                          rhs_records = middles.flat_map { |r|
         | 
| 46 | 
            -
                            association = r.association source_reflection.name
         | 
| 47 | 
            -
             | 
| 48 | 
            -
                            target_records_from_association(association)
         | 
| 49 | 
            -
                          }.compact
         | 
| 50 | 
            -
             | 
| 51 | 
            -
                          # Respect the order on `reflection_scope` if it exists, else use the natural order.
         | 
| 52 | 
            -
                          if reflection_scope.values[:order].present?
         | 
| 53 | 
            -
                            @id_map ||= id_to_index_map @preloaded_records
         | 
| 54 | 
            -
                            rhs_records.sort_by { |rhs| @id_map[rhs] }
         | 
| 55 | 
            -
                          else
         | 
| 56 | 
            -
                            rhs_records
         | 
| 16 | 
            +
                      owners.each do |owner|
         | 
| 17 | 
            +
                        through_records = Array(owner.association(through_reflection.name).target)
         | 
| 18 | 
            +
                        if already_loaded
         | 
| 19 | 
            +
                          if source_type = reflection.options[:source_type]
         | 
| 20 | 
            +
                            through_records = through_records.select do |record|
         | 
| 21 | 
            +
                              record[reflection.foreign_type] == source_type
         | 
| 22 | 
            +
                            end
         | 
| 57 23 | 
             
                          end
         | 
| 24 | 
            +
                        else
         | 
| 25 | 
            +
                          owner.association(through_reflection.name).reset if through_scope
         | 
| 26 | 
            +
                        end
         | 
| 27 | 
            +
                        result = through_records.flat_map do |record|
         | 
| 28 | 
            +
                          association = record.association(source_reflection.name)
         | 
| 29 | 
            +
                          target = association.target
         | 
| 30 | 
            +
                          association.reset if preload_scope
         | 
| 31 | 
            +
                          target
         | 
| 32 | 
            +
                        end
         | 
| 33 | 
            +
                        result.compact!
         | 
| 34 | 
            +
                        if reflection_scope
         | 
| 35 | 
            +
                          result.sort_by! { |rhs| preload_index[rhs] } if reflection_scope.order_values.any?
         | 
| 36 | 
            +
                          result.uniq! if reflection_scope.distinct_value
         | 
| 58 37 | 
             
                        end
         | 
| 38 | 
            +
                        associate_records_to_owner(owner, result)
         | 
| 59 39 | 
             
                      end
         | 
| 60 40 | 
             
                    end
         | 
| 61 41 |  | 
| 62 42 | 
             
                    private
         | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 65 | 
            -
                        id_map = {}
         | 
| 66 | 
            -
                        ids.each_with_index { |id, index| id_map[id] = index }
         | 
| 67 | 
            -
                        id_map
         | 
| 43 | 
            +
                      def through_reflection
         | 
| 44 | 
            +
                        reflection.through_reflection
         | 
| 68 45 | 
             
                      end
         | 
| 69 46 |  | 
| 70 | 
            -
                      def  | 
| 71 | 
            -
                         | 
| 72 | 
            -
             | 
| 47 | 
            +
                      def source_reflection
         | 
| 48 | 
            +
                        reflection.source_reflection
         | 
| 49 | 
            +
                      end
         | 
| 73 50 |  | 
| 74 | 
            -
             | 
| 75 | 
            -
                         | 
| 76 | 
            -
                           | 
| 77 | 
            -
                            owner.association(association_name).reset
         | 
| 78 | 
            -
                          }
         | 
| 51 | 
            +
                      def preload_index
         | 
| 52 | 
            +
                        @preload_index ||= @preloaded_records.each_with_object({}).with_index do |(id, result), index|
         | 
| 53 | 
            +
                          result[id] = index
         | 
| 79 54 | 
             
                        end
         | 
| 80 55 | 
             
                      end
         | 
| 81 56 |  | 
| 82 57 | 
             
                      def through_scope
         | 
| 83 58 | 
             
                        scope = through_reflection.klass.unscoped
         | 
| 84 | 
            -
                         | 
| 59 | 
            +
                        options = reflection.options
         | 
| 85 60 |  | 
| 86 61 | 
             
                        if options[:source_type]
         | 
| 87 62 | 
             
                          scope.where! reflection.foreign_type => options[:source_type]
         | 
| 88 | 
            -
                         | 
| 89 | 
            -
                           | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 94 | 
            -
             | 
| 95 | 
            -
                             | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 63 | 
            +
                        elsif !reflection_scope.where_clause.empty?
         | 
| 64 | 
            +
                          scope.where_clause = reflection_scope.where_clause
         | 
| 65 | 
            +
                          values = reflection_scope.values
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                          if includes = values[:includes]
         | 
| 68 | 
            +
                            scope.includes!(source_reflection.name => includes)
         | 
| 69 | 
            +
                          else
         | 
| 70 | 
            +
                            scope.includes!(source_reflection.name)
         | 
| 71 | 
            +
                          end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                          if values[:references] && !values[:references].empty?
         | 
| 74 | 
            +
                            scope.references!(values[:references])
         | 
| 75 | 
            +
                          else
         | 
| 76 | 
            +
                            scope.references!(source_reflection.table_name)
         | 
| 77 | 
            +
                          end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                          if joins = values[:joins]
         | 
| 80 | 
            +
                            scope.joins!(source_reflection.name => joins)
         | 
| 81 | 
            +
                          end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                          if left_outer_joins = values[:left_outer_joins]
         | 
| 84 | 
            +
                            scope.left_outer_joins!(source_reflection.name => left_outer_joins)
         | 
| 98 85 | 
             
                          end
         | 
| 99 86 |  | 
| 100 | 
            -
                          scope.references! values[:references]
         | 
| 101 87 | 
             
                          if scope.eager_loading? && order_values = values[:order]
         | 
| 102 88 | 
             
                            scope = scope.order(order_values)
         | 
| 103 89 | 
             
                          end
         | 
| 104 90 | 
             
                        end
         | 
| 105 91 |  | 
| 106 | 
            -
                        scope
         | 
| 92 | 
            +
                        scope unless scope.empty_scope?
         | 
| 107 93 | 
             
                      end
         | 
| 108 94 |  | 
| 109 | 
            -
                      def  | 
| 110 | 
            -
                         | 
| 95 | 
            +
                      def target_reflection_scope
         | 
| 96 | 
            +
                        if preload_scope
         | 
| 97 | 
            +
                          reflection_scope.merge(preload_scope)
         | 
| 98 | 
            +
                        elsif reflection.scope
         | 
| 99 | 
            +
                          reflection_scope
         | 
| 100 | 
            +
                        else
         | 
| 101 | 
            +
                          nil
         | 
| 102 | 
            +
                        end
         | 
| 111 103 | 
             
                      end
         | 
| 112 104 | 
             
                  end
         | 
| 113 105 | 
             
                end
         |