Class: ActiveRecord::Associations::JoinDependency::JoinAssociation
- Inherits:
-
JoinPart
- Object
- JoinPart
- ActiveRecord::Associations::JoinDependency::JoinAssociation
- Includes:
- ActiveRecord::Associations::JoinHelper
- Defined in:
- 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(reflection, 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_relation(joining_relation) ⇒ Object
- #join_to(manager) ⇒ Object
- #scope_chain ⇒ Object
- #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.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/active_record/associations/join_dependency/join_association.rb', line 33 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 '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 '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 '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 '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 '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 '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 '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
165 166 167 |
# File 'lib/active_record/associations/join_dependency/join_association.rb', line 165 def aliased_table_name table.table_alias || table.name end |
#build_constraint(reflection, 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
143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/active_record/associations/join_dependency/join_association.rb', line 143 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 |
#find_parent_in(other_join_dependency) ⇒ Object
56 57 58 59 60 61 62 63 64 65 |
# File '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_relation(joining_relation) ⇒ Object
156 157 158 159 |
# File 'lib/active_record/associations/join_dependency/join_association.rb', line 156 def join_relation(joining_relation) self.join_type = Arel::OuterJoin joining_relation.joins(self) end |
#join_to(manager) ⇒ 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 |
# File 'lib/active_record/associations/join_dependency/join_association.rb', line 67 def join_to(manager) tables = @tables.dup foreign_table = parent_table foreign_klass = parent.base_klass # 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... manager.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) scope_chain_items = scope_chain[i] if reflection.type scope_chain_items += [ ActiveRecord::Relation.new(reflection.klass, table) .where(reflection.type => foreign_klass.base_class.name) ] end scope_chain_items += [reflection.klass.send(:build_default_scope, ActiveRecord::Relation.new(reflection.klass, table))].compact scope_chain_items.each do |item| unless item.is_a?(Relation) item = ActiveRecord::Relation.new(reflection.klass, table).instance_exec(self, &item) end constraint = constraint.and(item.arel.constraints) unless item.arel.constraints.empty? end manager.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 manager end |
#scope_chain ⇒ Object
169 170 171 |
# File 'lib/active_record/associations/join_dependency/join_association.rb', line 169 def scope_chain @scope_chain ||= reflection.scope_chain.reverse end |
#table ⇒ Object
161 162 163 |
# File 'lib/active_record/associations/join_dependency/join_association.rb', line 161 def table tables.last end |