class Sequel::Plugins::ManyThroughMany::ManyThroughManyAssociationReflection
The AssociationReflection subclass for many_through_many associations.
Constants
- FINALIZE_SETTINGS
Public Instance Methods
Source
# File lib/sequel/plugins/many_through_many.rb 87 def cloneable?(ref) 88 ref[:type] == :many_through_many || ref[:type] == :one_through_many 89 end
many_through_many and one_through_many associations can be clones
Source
# File lib/sequel/plugins/many_through_many.rb 93 def default_associated_key_alias 94 self[:uses_left_composite_keys] ? (0...self[:through].first[:left].length).map{|i| :"x_foreign_key_#{i}_x"} : :x_foreign_key_x 95 end
The default associated key alias(es) to use when eager loading associations via eager.
Source
# File lib/sequel/plugins/many_through_many.rb 112 def finalize_settings 113 FINALIZE_SETTINGS 114 end
Source
# File lib/sequel/plugins/many_through_many.rb 117 def join_table_alias 118 final_reverse_edge[:alias] 119 end
The alias for the first join table.
Source
# File lib/sequel/plugins/many_through_many.rb 122 def reciprocal 123 nil 124 end
Many through many associations donβt have a reciprocal
Source
# File lib/sequel/plugins/many_through_many.rb 127 def separate_query_per_table? 128 self[:separate_query_per_table] 129 end
Whether a separate query should be used for each join table.
Private Instance Methods
Source
# File lib/sequel/plugins/many_through_many.rb 133 def _associated_dataset 134 ds = associated_class 135 if separate_query_per_table? 136 ds = ds.dataset 137 else 138 (reverse_edges + [final_reverse_edge]).each do |t| 139 h = {:qualify=>:deep} 140 if t[:alias] != t[:table] 141 h[:table_alias] = t[:alias] 142 end 143 ds = ds.join(t[:table], Array(t[:left]).zip(Array(t[:right])), h) 144 end 145 end 146 ds 147 end
Source
# File lib/sequel/plugins/many_through_many.rb 188 def calculate_edges 189 es = [{:left_table=>self[:model].table_name, :left_key=>self[:left_primary_key_column]}] 190 self[:through].each do |t| 191 es.last.merge!(:right_key=>t[:left], :right_table=>t[:table], :join_type=>t[:join_type]||self[:graph_join_type], :conditions=>(t[:conditions]||[]).to_a, :block=>t[:block]) 192 es.last[:only_conditions] = t[:only_conditions] if t.include?(:only_conditions) 193 es << {:left_table=>t[:table], :left_key=>t[:right]} 194 end 195 es.last.merge!(:right_key=>right_primary_key, :right_table=>associated_class.table_name) 196 edges = es.map do |e| 197 h = {:table=>e[:right_table], :left=>e[:left_key], :right=>e[:right_key], :conditions=>e[:conditions], :join_type=>e[:join_type], :block=>e[:block]} 198 h[:only_conditions] = e[:only_conditions] if e.include?(:only_conditions) 199 h 200 end 201 reverse_edges = es.reverse.map{|e| {:table=>e[:left_table], :left=>e[:left_key], :right=>e[:right_key]}} 202 reverse_edges.pop 203 calculate_reverse_edge_aliases(reverse_edges) 204 final_reverse_edge = reverse_edges.pop 205 final_reverse_alias = final_reverse_edge[:alias] 206 207 h = {:final_edge=>edges.pop, 208 :final_reverse_edge=>final_reverse_edge, 209 :edges=>edges, 210 :reverse_edges=>reverse_edges, 211 :predicate_key=>qualify(final_reverse_alias, edges.first[:right]), 212 :associated_key_table=>final_reverse_edge[:alias], 213 } 214 h.each{|k, v| cached_set(k, v)} 215 h 216 end
Transform the :through option into a list of edges and reverse edges to use to join tables when loading the association.
Source
# File lib/sequel/plugins/many_through_many.rb 171 def calculate_reverse_edge_aliases(reverse_edges) 172 aliases = [associated_class.table_name] 173 reverse_edges.each do |e| 174 table_alias = e[:table] 175 if aliases.include?(table_alias) 176 i = 0 177 table_alias = while true 178 ta = :"#{table_alias}_#{i}" 179 break ta unless aliases.include?(ta) 180 i += 1 181 end 182 end 183 aliases.push(e[:alias] = table_alias) 184 end 185 end
Make sure to use unique table aliases when lazy loading or eager loading
Source
# File lib/sequel/plugins/many_through_many.rb 218 def filter_by_associations_limit_key 219 fe = edges.first 220 Array(qualify(fe[:table], fe[:right])) + Array(qualify(associated_class.table_name, associated_class.primary_key)) 221 end
Source
# File lib/sequel/plugins/many_through_many.rb 149 def lateral_subquery_filter_limit_strategy_conditions_key 150 qualify(reverse_edges.first[:table], reverse_edges.first[:left]) 151 end
Source
# File lib/sequel/plugins/many_through_many.rb 157 def lateral_subquery_filter_limit_strategy_filter_dataset(ds, obj) 158 first_edge, *remaining_edges = edges 159 filter_ds = ds.db.from(first_edge[:table]). 160 select(*qualify(first_edge[:table], first_edge[:right])). 161 where(lateral_subquery_filter_limit_strategy_conditions(obj)) 162 163 remaining_edges.each do |edge| 164 filter_ds = filter_ds.join(edge[:table], Array(edge[:right]).zip(Array(edge[:left]))) 165 end 166 167 ds.where(qualify(self[:model].table_name, self[:left_primary_key]) => filter_ds) 168 end
Source
# File lib/sequel/plugins/many_through_many.rb 153 def lateral_subquery_filter_limit_strategy_filter_lateral_dataset(ds) 154 ds.where(Array(qualify(edges.first[:table], edges.first[:right])).zip(Array(qualify(self[:model].table_name, edges.first[:left])))) 155 end