Module: UnionOf::JoinAssociationExtension

Defined in:
lib/union_of/railtie.rb

Instance Method Summary collapse

Instance Method Details

#join_constraints(foreign_table, foreign_klass, join_type, alias_tracker) ⇒ Object

Overloads Rails internals to prepend our left outer joins onto the join chain since Rails unfortunately does not do this for us (it can do inner joins via the LeadingJoin arel node, but it can’t do outer joins because there is no LeadingOuterJoin node).



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/union_of/railtie.rb', line 89

def join_constraints(foreign_table, foreign_klass, join_type, alias_tracker)
  chain = reflection.chain.reverse
  joins = super

  # FIXME(ezekg) This is inefficient (we're recreating reflection scopes).
  chain.zip(joins).each do |reflection, join|
    klass = reflection.klass
    table = join.left

    if reflection.union_of?
      scope = reflection.join_scope(table, foreign_table, foreign_klass, alias_tracker)
      arel  = scope.arel(alias_tracker.aliases)

      # Splice union dependencies, i.e. left joins, into the join chain. This is the least
      # intrusive way of doing this, since we don't want to overload AR internals.
      unless arel.join_sources.empty?
        index = joins.index(join)

        unless (constraints = arel.constraints).empty?
          right = join.right

          right.expr = constraints # updated aliases
        end

        joins.insert(index, *arel.join_sources)
      end
    end

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

  joins
end