Class: ActiveRecord::Associations::JoinDependency::JoinAssociation

Inherits:
JoinPart
  • Object
show all
Includes:
ActiveRecord::Associations::JoinHelper
Defined in:
activerecord/lib/active_record/associations/join_dependency/join_association.rb

Overview

:nodoc:

Instance Attribute Summary (collapse)

Attributes inherited from JoinPart

#active_record

Instance Method Summary (collapse)

Methods inherited from JoinPart

#aliased_primary_key, #aliased_table, #column_names_with_alias, #extract_record, #instantiate, #record_id

Constructor Details

- (JoinAssociation) initialize(reflection, join_dependency, parent = nil)

A new instance of JoinAssociation



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'activerecord/lib/active_record/associations/join_dependency/join_association.rb', line 33

def initialize(reflection, join_dependency, parent = nil)
  reflection.check_validity!

  if reflection.options[:polymorphic]
    raise EagerLoadPolymorphicError.new(reflection)
  end

  super(reflection.klass)

  @reflection      = reflection
  @join_dependency = join_dependency
  @parent          = parent
  @join_type       = Arel::InnerJoin
  @aliased_prefix  = "t#{ join_dependency.join_parts.size }"
  @tables          = construct_tables.reverse
end

Instance Attribute Details

- (Object) aliased_prefix (readonly)

These implement abstract methods from the superclass



23
24
25
# File 'activerecord/lib/active_record/associations/join_dependency/join_association.rb', line 23

def aliased_prefix
  @aliased_prefix
end

- (Object) join_dependency (readonly)

The JoinDependency object which this JoinAssociation exists within. This is mainly relevant for generating aliases which do not conflict with other joins which are part of the query.



13
14
15
# File 'activerecord/lib/active_record/associations/join_dependency/join_association.rb', line 13

def join_dependency
  @join_dependency
end

- (Object) join_type

What type of join will be generated, either Arel::InnerJoin (default) or Arel::OuterJoin



20
21
22
# File 'activerecord/lib/active_record/associations/join_dependency/join_association.rb', line 20

def join_type
  @join_type
end

- (Object) parent (readonly)

A JoinBase instance representing the active record we are joining onto. (So in Author.has_many :posts, the Author would be that base record.)



17
18
19
# File 'activerecord/lib/active_record/associations/join_dependency/join_association.rb', line 17

def parent
  @parent
end

- (Object) reflection (readonly)

The reflection of the association represented



8
9
10
# File 'activerecord/lib/active_record/associations/join_dependency/join_association.rb', line 8

def reflection
  @reflection
end

- (Object) tables (readonly)

Returns the value of attribute tables



25
26
27
# File 'activerecord/lib/active_record/associations/join_dependency/join_association.rb', line 25

def tables
  @tables
end

Instance Method Details

- (Object) ==(other)



50
51
52
53
54
# File 'activerecord/lib/active_record/associations/join_dependency/join_association.rb', line 50

def ==(other)
  other.class == self.class &&
    other.reflection == reflection &&
    other.parent == parent
end

- (Object) aliased_table_name



133
134
135
# File 'activerecord/lib/active_record/associations/join_dependency/join_association.rb', line 133

def aliased_table_name
  table.table_alias || table.name
end

- (Object) build_constraint(reflection, table, key, foreign_table, foreign_key)



111
112
113
114
115
116
117
118
119
120
121
122
# File 'activerecord/lib/active_record/associations/join_dependency/join_association.rb', line 111

def build_constraint(reflection, table, key, foreign_table, foreign_key)
  constraint = table[key].eq(foreign_table[foreign_key])

  if reflection.klass.finder_needs_type_condition?
    constraint = table.create_and([
      constraint,
      reflection.klass.send(:type_condition, table)
    ])
  end

  constraint
end

- (Object) conditions



137
138
139
# File 'activerecord/lib/active_record/associations/join_dependency/join_association.rb', line 137

def conditions
  @conditions ||= reflection.conditions.reverse
end

- (Object) find_parent_in(other_join_dependency)



56
57
58
59
60
# File 'activerecord/lib/active_record/associations/join_dependency/join_association.rb', line 56

def find_parent_in(other_join_dependency)
  other_join_dependency.join_parts.detect do |join_part|
    parent == join_part
  end
end

- (Object) join_relation(joining_relation)



124
125
126
127
# File 'activerecord/lib/active_record/associations/join_dependency/join_association.rb', line 124

def join_relation(joining_relation)
  self.join_type = Arel::OuterJoin
  joining_relation.joins(self)
end

- (Object) join_to(relation)



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'activerecord/lib/active_record/associations/join_dependency/join_association.rb', line 62

def join_to(relation)
  tables        = @tables.dup
  foreign_table = parent_table
  foreign_klass = parent.active_record

  # The chain starts with the target table, but we want to end with it here (makes
  # more sense in this context), so we reverse
  chain.reverse.each_with_index do |reflection, i|
    table = tables.shift

    case reflection.source_macro
    when :belongs_to
      key         = reflection.association_primary_key
      foreign_key = reflection.foreign_key
    when :has_and_belongs_to_many
      # Join the join table first...
      relation.from(join(
        table,
        table[reflection.foreign_key].
          eq(foreign_table[reflection.active_record_primary_key])
      ))

      foreign_table, table = table, tables.shift

      key         = reflection.association_primary_key
      foreign_key = reflection.association_foreign_key
    else
      key         = reflection.foreign_key
      foreign_key = reflection.active_record_primary_key
    end

    constraint = build_constraint(reflection, table, key, foreign_table, foreign_key)

    conditions = self.conditions[i].dup
    conditions << { reflection.type => foreign_klass.base_class.name } if reflection.type

    unless conditions.empty?
      constraint = constraint.and(sanitize(conditions, table))
    end

    relation.from(join(table, constraint))

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

  relation
end

- (Object) table



129
130
131
# File 'activerecord/lib/active_record/associations/join_dependency/join_association.rb', line 129

def table
  tables.last
end