Class: ActiveRecord::Associations::JoinDependency::JoinAssociation
- Includes:
- ActiveRecord::Associations::JoinHelper
- Defined in:
- activerecord/lib/active_record/associations/join_dependency/join_association.rb
Overview
:nodoc:
Instance Attribute Summary collapse
-
#aliased_prefix ⇒ Object
readonly
These implement abstract methods from the superclass.
-
#join_dependency ⇒ Object
readonly
The JoinDependency object which this JoinAssociation exists within.
-
#join_type ⇒ Object
What type of join will be generated, either Arel::InnerJoin (default) or Arel::OuterJoin.
-
#parent ⇒ Object
readonly
A JoinBase instance representing the active record we are joining onto.
-
#reflection ⇒ Object
readonly
The reflection of the association represented.
-
#tables ⇒ Object
readonly
Returns the value of attribute tables.
Attributes inherited from JoinPart
Instance Method Summary collapse
- #==(other) ⇒ Object
- #aliased_table_name ⇒ Object
-
#build_constraint(klass, table, key, foreign_table, foreign_key) ⇒ Object
Builds equality condition.
- #find_parent_in(other_join_dependency) ⇒ Object
-
#initialize(reflection, join_dependency, parent = nil) ⇒ JoinAssociation
constructor
A new instance of JoinAssociation.
- #join_constraints ⇒ Object
- #join_relation(joining_relation) ⇒ Object
- #parent_table_name ⇒ Object (also: #alias_suffix)
- #table ⇒ Object
Methods inherited from JoinPart
#aliased_primary_key, #aliased_table, #column_names_with_alias, #extract_record, #instantiate, #record_id
Constructor Details
#initialize(reflection, join_dependency, parent = nil) ⇒ JoinAssociation
Returns a new instance of JoinAssociation.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'activerecord/lib/active_record/associations/join_dependency/join_association.rb', line 30 def initialize(reflection, join_dependency, parent = nil) reflection.check_validity! if reflection.[: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
#aliased_prefix ⇒ Object (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 |
#join_dependency ⇒ Object (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 |
#join_type ⇒ Object
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 |
#parent ⇒ Object (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 |
#reflection ⇒ Object (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 |
#tables ⇒ Object (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
#==(other) ⇒ Object
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 |
#aliased_table_name ⇒ Object
174 175 176 |
# File 'activerecord/lib/active_record/associations/join_dependency/join_association.rb', line 174 def aliased_table_name table.table_alias || table.name end |
#build_constraint(klass, table, key, foreign_table, foreign_key) ⇒ Object
Builds equality condition.
Example:
class Physician < ActiveRecord::Base
has_many :appointments
end
If I execute `Physician.joins(:appointments).to_a` then
reflection #=> #<ActiveRecord::Reflection::AssociationReflection @macro=:has_many ...>
table #=> #<Arel::Table @name="appointments" ...>
key #=> physician_id
foreign_table #=> #<Arel::Table @name="physicians" ...>
foreign_key #=> id
152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'activerecord/lib/active_record/associations/join_dependency/join_association.rb', line 152 def build_constraint(klass, table, key, foreign_table, foreign_key) constraint = table[key].eq(foreign_table[foreign_key]) if klass.finder_needs_type_condition? constraint = table.create_and([ constraint, klass.send(:type_condition, table) ]) end constraint end |
#find_parent_in(other_join_dependency) ⇒ Object
56 57 58 59 60 61 62 63 64 65 |
# 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| case parent when JoinBase parent.base_klass == join_part.base_klass else parent == join_part end end end |
#join_constraints ⇒ Object
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 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'activerecord/lib/active_record/associations/join_dependency/join_association.rb', line 67 def join_constraints joins = [] tables = @tables.dup foreign_table = parent.table foreign_klass = parent.base_klass scope_chain_iter = reflection.scope_chain.reverse_each # 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 do |reflection| table = tables.shift klass = reflection.klass 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... joins << 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(klass, table, key, foreign_table, foreign_key) scope_chain_items = scope_chain_iter.next.map do |item| if item.is_a?(Relation) item else ActiveRecord::Relation.create(klass, table).instance_exec(self, &item) end end if reflection.type scope_chain_items << ActiveRecord::Relation.create(klass, table) .where(reflection.type => foreign_klass.base_class.name) end scope_chain_items.concat [klass.send(:build_default_scope)].compact rel = scope_chain_items.inject(scope_chain_items.shift) do |left, right| left.merge right end if rel && !rel.arel.constraints.empty? constraint = constraint.and rel.arel.constraints end joins << join(table, constraint) # The current table in this iteration becomes the foreign table in the next foreign_table, foreign_klass = table, klass end joins end |
#join_relation(joining_relation) ⇒ Object
165 166 167 168 |
# File 'activerecord/lib/active_record/associations/join_dependency/join_association.rb', line 165 def join_relation(joining_relation) self.join_type = Arel::OuterJoin joining_relation.joins(self) end |
#parent_table_name ⇒ Object Also known as: alias_suffix
47 |
# File 'activerecord/lib/active_record/associations/join_dependency/join_association.rb', line 47 def parent_table_name; parent.table_name; end |
#table ⇒ Object
170 171 172 |
# File 'activerecord/lib/active_record/associations/join_dependency/join_association.rb', line 170 def table tables.last end |