class ActiveRecord::Associations::JoinDependency

Attributes

references[RW]

Public Class Methods

new(base, table, associations, references:) click to toggle source
# File lib/praxis/extensions/attribute_filtering/active_record_patches/5x.rb, line 48
def initialize(base, table, associations, references:)
  tree = self.class.make_tree associations
  @references = references # Save the references values into the instance (to use during build)
  @join_root = JoinBase.new(base, table, build(tree, base))
end

Private Instance Methods

build(associations, base_klass, path: [PRAXIS_JOIN_ALIAS_PREFIX]) click to toggle source

Praxis: build for is shared for 5x and 6.0

# File lib/praxis/extensions/attribute_filtering/active_record_patches/5x.rb, line 73
def build(associations, base_klass, path: [PRAXIS_JOIN_ALIAS_PREFIX])
  associations.map do |name, right|
    reflection = find_reflection base_klass, name
    reflection.check_validity!
    reflection.check_eager_loadable!

    raise EagerLoadPolymorphicError, reflection if reflection.polymorphic?

    # Praxis: set an alias_path in the JoinAssociation if its path matches a requested reference
    child_path = path && !path.empty? ? path + [name] : nil
    association = JoinAssociation.new(reflection, build(right, reflection.klass, path: child_path))
    association.alias_path = child_path if references.include?(child_path.join('/'))
    association
  end
end
make_constraints(parent, child, join_type) click to toggle source
# File lib/praxis/extensions/attribute_filtering/active_record_patches/6_1_plus.rb, line 11
def make_constraints(parent, child, join_type)
  foreign_table = parent.table
  foreign_klass = parent.base_klass
  child.join_constraints(foreign_table, foreign_klass, join_type, alias_tracker) do |reflection|
    table, terminated = @joined_tables[reflection]
    root = reflection == child.reflection

    if table && (!root || !terminated)
      @joined_tables[reflection] = [table, root] if root
      next table, true
    end

    table_name = @references[reflection.name.to_sym]
    # Praxis: set an alias_path in the JoinAssociation if its path matches a requested reference
    table_name ||= @references[child&.alias_path.join('/').to_sym]

    table = alias_tracker.aliased_table_for(reflection.klass.arel_table, table_name) 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.concat child.children.flat_map { |c| make_constraints(child, c, join_type) }
end
table_aliases_for(parent, node) click to toggle source

Praxis: table aliases for is shared for 5x and 6.0

# File lib/praxis/extensions/attribute_filtering/active_record_patches/5x.rb, line 55
def table_aliases_for(parent, node)
  node.reflection.chain.map do |reflection|
    is_root_reflection = reflection == node.reflection
    table = alias_tracker.aliased_table_for(
      reflection.table_name,
      table_alias_for(reflection, parent, !is_root_reflection),
      reflection.klass.type_caster
    )
    # through tables do not need a special alias_path alias (as they shouldn't really referenced by the client)
    if is_root_reflection && node.alias_path
      table = table.left if table.is_a?(Arel::Nodes::TableAlias) # un-alias it if necessary
      table = table.alias(node.alias_path.join('/'))
    end
    table
  end
end