module Polyamorous::JoinDependencyExtensions

Public Instance Methods

build(associations, base_klass) click to toggle source

Replaces ActiveRecord::Associations::JoinDependency#build

# File lib/polyamorous/activerecord/join_dependency.rb, line 4
def build(associations, base_klass)
  associations.map do |name, right|
    if name.is_a? Join
      reflection = find_reflection base_klass, name.name
      reflection.check_validity!
      reflection.check_eager_loadable!

      klass = if reflection.polymorphic?
        name.klass || base_klass
      else
        reflection.klass
      end
      JoinAssociation.new(reflection, build(right, klass), name.klass, name.type)
    else
      reflection = find_reflection base_klass, name
      reflection.check_validity!
      reflection.check_eager_loadable!

      if reflection.polymorphic?
        raise ActiveRecord::EagerLoadPolymorphicError.new(reflection)
      end
      JoinAssociation.new(reflection, build(right, reflection.klass))
    end
  end
end
construct_tables_for_association!(join_root, association) click to toggle source
# File lib/polyamorous/activerecord/join_dependency.rb, line 50
def construct_tables_for_association!(join_root, association)
  tables = table_aliases_for(join_root, association)
  association.table = tables.first
  tables
end
join_constraints(joins_to_add, alias_tracker, references) click to toggle source
# File lib/polyamorous/activerecord/join_dependency.rb, line 30
def join_constraints(joins_to_add, alias_tracker, references)
  @alias_tracker = alias_tracker
  @joined_tables = {}
  @references = {}

  references.each do |table_name|
    @references[table_name.to_sym] = table_name if table_name.is_a?(String)
  end

  joins = make_join_constraints(join_root, join_type)

  joins.concat joins_to_add.flat_map { |oj|
    if join_root.match?(oj.join_root) && join_root.table.name == oj.join_root.table.name
      walk join_root, oj.join_root, oj.join_type
    else
      make_join_constraints(oj.join_root, oj.join_type)
    end
  }
end

Private Instance Methods

table_aliases_for(parent, node) click to toggle source
# File lib/polyamorous/activerecord/join_dependency.rb, line 58
def table_aliases_for(parent, node)
  @joined_tables ||= {}
  node.reflection.chain.map { |reflection|
    table, terminated = @joined_tables[reflection]
    root = reflection == node.reflection

    if table && (!root || !terminated)
      @joined_tables[reflection] = [table, true] if root
      table
    else
      table = alias_tracker.aliased_table_for(reflection.klass.arel_table) do
        name = reflection.alias_candidate(parent.table_name)
        root ? name : "#{name}_join"
      end
      @joined_tables[reflection] ||= [table, root] if join_type == Arel::Nodes::OuterJoin
      table
    end
  }
end