Class: ActiveRecord::HasSomeOfMany::RelationRewriter

Inherits:
Object
  • Object
show all
Defined in:
lib/activerecord/has_some_of_many/relation_rewriter.rb

Instance Method Summary collapse

Constructor Details

#initialize(relation) ⇒ RelationRewriter

Returns a new instance of RelationRewriter.



6
7
8
# File 'lib/activerecord/has_some_of_many/relation_rewriter.rb', line 6

def initialize(relation)
  @relation = relation
end

Instance Method Details

#alias_table(alias_name) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/activerecord/has_some_of_many/relation_rewriter.rb', line 10

def alias_table(alias_name)
  relation_class = @relation.klass
  original_table = relation_class.arel_table
  alias_table = original_table.alias(alias_name)

  where_clause = recursively_alias_table(@relation.where_clause.ast, original_table, alias_table)
  order_clause = @relation.order_values.map do |order|
    if order.respond_to?(:expr)
      order.expr = alias_table[order.expr.name] if order.expr.relation == original_table
    end
    order
  end

  new_relation = @relation.dup.unscope(:select, :where, :order)
  new_relation.instance_variable_set(:@table, alias_table) # Is there a better way to modify the original relation?
  new_relation.where(where_clause).order(order_clause)
end

#recursively_alias_table(node, original_table, alias_table) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/activerecord/has_some_of_many/relation_rewriter.rb', line 28

def recursively_alias_table(node, original_table, alias_table)
  case node
  when Arel::Nodes::And, Arel::Nodes::Or
    return nil if node.children.empty?

    # Recurse for left and right nodes
    node.children.each { |child| recursively_alias_table(child, original_table, alias_table) }
    node
  when Arel::Nodes::Grouping
    # Recurse for the expression inside the grouping
    node.expr = recursively_alias_table(node.expr, original_table, alias_table)
    node
  when Arel::Nodes::Equality, Arel::Nodes::GreaterThan, Arel::Nodes::LessThan, Arel::Nodes::HomogeneousIn
    # For conditions, modify left-hand side (the column)
    if node.left.relation == original_table
      node.left.relation = alias_table
    end
    node
  else
    node
  end
end