join_association.rb 1.9 KB
Newer Older
1 2
# frozen_string_literal: true

3
require "active_record/associations/join_dependency/join_part"
4

5 6 7 8 9 10 11
module ActiveRecord
  module Associations
    class JoinDependency # :nodoc:
      class JoinAssociation < JoinPart # :nodoc:
        # The reflection of the association represented
        attr_reader :reflection

12
        attr_accessor :tables
13

14
        def initialize(reflection, children, alias_tracker)
15
          super(reflection.klass, children)
16

17 18 19
          @alias_tracker = alias_tracker
          @reflection    = reflection
          @tables        = nil
20 21
        end

A
Aaron Patterson 已提交
22
        def match?(other)
A
Aaron Patterson 已提交
23
          return true if self == other
A
Aaron Patterson 已提交
24 25 26
          super && reflection == other.reflection
        end

27
        def join_constraints(foreign_table, foreign_klass, join_type, tables, chain)
28
          joins         = []
29
          tables        = tables.reverse
30

31 32
          # The chain starts with the target table, but we want to end with it here (makes
          # more sense in this context), so we reverse
33
          chain.reverse_each do |reflection|
J
Jon Leighton 已提交
34
            table = tables.shift
35
            klass = reflection.klass
J
Jon Leighton 已提交
36

37
            constraint = reflection.build_join_constraint(table, foreign_table)
38

39
            joins << table.create_join(table, table.create_on(constraint), join_type)
40

41
            join_scope = reflection.join_scope(table, foreign_klass)
42
            arel = join_scope.arel(alias_tracker.aliases)
43

44 45
            if arel.constraints.any?
              joins.concat arel.join_sources
46
              right = joins.last.right
47
              right.expr = right.expr.and(arel.constraints)
48 49
            end

50
            # The current table in this iteration becomes the foreign table in the next
51
            foreign_table, foreign_klass = table, klass
52 53
          end

54
          joins
55 56
        end

57
        def table
58
          tables.first
59
        end
60 61 62

        protected
          attr_reader :alias_tracker
63 64 65 66
      end
    end
  end
end