Module: Polyamorous::JoinDependencyExtensions

Defined in:
lib/polyamorous/activerecord_4.2_ruby_2/join_dependency.rb,
lib/polyamorous/activerecord_5.1_ruby_2/join_dependency.rb,
lib/polyamorous/activerecord_4.2_ruby_1.9/join_dependency.rb,
lib/polyamorous/activerecord_5.2.0_ruby_2/join_dependency.rb,
lib/polyamorous/activerecord_3_and_4.0_ruby_1.9/join_dependency.rb,
lib/polyamorous/activerecord_4.1_ruby_2/make_polyamorous_inner_joins.rb

Defined Under Namespace

Modules: ClassMethods

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/polyamorous/activerecord_4.2_ruby_1.9/join_dependency.rb', line 6

def self.included(base)
  base.extend ClassMethods
  base.class_eval do
    class << self
      alias_method :walk_tree_without_polymorphism, :walk_tree
      alias_method :walk_tree, :walk_tree_with_polymorphism
    end

    alias_method :build_without_polymorphism, :build
    alias_method :build, :build_with_polymorphism

    alias_method :join_constraints_without_polymorphism, :join_constraints
    alias_method :join_constraints, :join_constraints_with_polymorphism
  end
end

Instance Method Details

#_join_partsObject



40
41
42
# File 'lib/polyamorous/activerecord_3_and_4.0_ruby_1.9/join_dependency.rb', line 40

def _join_parts
  @joins
end

#build(associations, base_klass) ⇒ Object

Replaces ActiveRecord::Associations::JoinDependency#build



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/polyamorous/activerecord_5.1_ruby_2/join_dependency.rb', line 7

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! if ActiveRecord::VERSION::MAJOR >= 5

      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 ActiveRecord::VERSION::MAJOR >= 5

      if reflection.polymorphic?
        raise ActiveRecord::EagerLoadPolymorphicError.new(reflection)
      end
      JoinAssociation.new reflection, build(right, reflection.klass)
    end
  end
end

#build_join_association_respecting_polymorphism(reflection, parent, klass) ⇒ Object



43
44
45
46
47
48
49
# File 'lib/polyamorous/activerecord_5.1_ruby_2/join_dependency.rb', line 43

def build_join_association_respecting_polymorphism(reflection, parent, klass)
  if reflection.polymorphic? && klass
    JoinAssociation.new(reflection, self, klass)
  else
    JoinAssociation.new(reflection, self)
  end
end

#build_with_polymorphism(associations, parent = nil, join_type = InnerJoin) ⇒ Object

Replaces ActiveRecord::Associations::JoinDependency#build



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/polyamorous/activerecord_4.2_ruby_1.9/join_dependency.rb', line 24

def build_with_polymorphism(associations, base_klass)
  associations.map do |name, right|
    if name.is_a? Join
      reflection = find_reflection base_klass, name.name
      reflection.check_validity!
      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!
      if reflection.polymorphic?
        raise ActiveRecord::EagerLoadPolymorphicError.new(reflection)
      end
      JoinAssociation.new reflection, build(right, reflection.klass)
    end
  end
end

#find_join_association_respecting_polymorphism(reflection, parent, klass) ⇒ Object



33
34
35
36
37
38
39
40
41
# File 'lib/polyamorous/activerecord_5.1_ruby_2/join_dependency.rb', line 33

def find_join_association_respecting_polymorphism(reflection, parent, klass)
  if association = parent.children.find { |j| j.reflection == reflection }
    unless reflection.polymorphic?
      association
    else
      association if association.base_klass == klass
    end
  end
end

#graft_with_polymorphism(*associations) ⇒ Object



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/polyamorous/activerecord_3_and_4.0_ruby_1.9/join_dependency.rb', line 14

def graft_with_polymorphism(*associations)
  associations.each do |association|
    unless join_associations.detect { |a| association == a }
      if association.reflection.options[:polymorphic]
        build(
          Join.new(
            association.reflection.name,
            association.join_type,
            association.reflection.klass
            ),
          association.find_parent_in(self) || join_base,
          association.join_type
          )
      else
        build(
          association.reflection.name,
          association.find_parent_in(self) || join_base,
          association.join_type
          )
      end
    end
  end
  self
end

#join_constraints(outer_joins, join_type) ⇒ Object

Replaces ActiveRecord::Associations::JoinDependency#join_constraints

This internal method was changed in Rails 5.0 by commit github.com/rails/rails/commit/e038975 which added left_outer_joins (see #make_polyamorous_left_outer_joins below) and added passing an additional argument, ‘join_type`, to #join_constraints.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/polyamorous/activerecord_4.2_ruby_2/join_dependency.rb', line 9

def join_constraints(outer_joins)
  joins = join_root.children.flat_map { |child|
    make_polyamorous_inner_joins join_root, child
  }
  joins.concat outer_joins.flat_map { |oj|
    if join_root.match? oj.join_root
      walk(join_root, oj.join_root)
    else
      oj.join_root.children.flat_map { |child|
        make_outer_joins(oj.join_root, child)
      }
    end
  }
end

#join_constraints_with_polymorphism(outer_joins) ⇒ Object

Replaces ActiveRecord::Associations::JoinDependency#join_constraints to call #make_polyamorous_inner_joins instead of #make_inner_joins



49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/polyamorous/activerecord_4.2_ruby_1.9/join_dependency.rb', line 49

def join_constraints_with_polymorphism(outer_joins)
  joins = join_root.children.flat_map { |child|
    make_polyamorous_inner_joins join_root, child
  }
  joins.concat outer_joins.flat_map { |oj|
    if join_root.match? oj.join_root
      walk(join_root, oj.join_root)
    else
      oj.join_root.children.flat_map { |child|
        make_outer_joins(oj.join_root, child)
      }
    end
  }
end

#make_polyamorous_inner_joins(parent, child) ⇒ Object

Replaces ActiveRecord::Associations::JoinDependency#make_inner_joins



94
95
96
97
98
99
100
101
102
# File 'lib/polyamorous/activerecord_5.1_ruby_2/join_dependency.rb', line 94

def make_polyamorous_inner_joins(parent, child)
  tables    = child.tables
  join_type = child.join_type || Arel::Nodes::InnerJoin
  info      = make_constraints parent, child, tables, join_type

  [info] + child.children.flat_map { |c|
    make_polyamorous_inner_joins(child, c)
  }
end