Class: ActiveRecord::Associations::Preloader::Branch
Do not use. This class is for internal use only.
Relationships & Source Files | |
Inherits: | Object |
Defined in: | activerecord/lib/active_record/associations/preloader/branch.rb |
Class Method Summary
Instance Attribute Summary
- #associate_by_default readonly
- #association readonly
- #children readonly
- #done? ⇒ Boolean readonly
- #parent readonly
- #polymorphic? ⇒ Boolean readonly
- #preloaded_records rw
- #preloaded_records=(value) rw
- #root? ⇒ Boolean readonly
- #scope readonly
Instance Method Summary
- #future_classes
- #grouped_records
- #immediate_future_classes
- #likely_reflections
- #loaders
- #preloaders_for_reflection(reflection, reflection_records)
- #runnable_loaders
- #source_records
- #target_classes
- #build_children(children) private
-
#preloader_for(reflection)
private
Returns a class containing the logic needed to load preload the data and attach it to a relation.
Constructor Details
.new(association:, children:, parent:, associate_by_default:, scope:) ⇒ Branch
# File 'activerecord/lib/active_record/associations/preloader/branch.rb', line 11
def initialize(association:, children:, parent:, associate_by_default:, scope:) @association = if association begin @association = association.to_sym rescue NoMethodError raise ArgumentError, "Association names must be Symbol or String, got: #{association.class.name}" end end @parent = parent @scope = scope @associate_by_default = associate_by_default @children = build_children(children) @loaders = nil end
Instance Attribute Details
#associate_by_default (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/associations/preloader/branch.rb', line 8
attr_reader :scope, :associate_by_default
#association (readonly)
[ GitHub ]#children (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/associations/preloader/branch.rb', line 7
attr_reader :association, :children, :parent
#done? ⇒ Boolean
(readonly)
[ GitHub ]
# File 'activerecord/lib/active_record/associations/preloader/branch.rb', line 72
def done? root? || (@loaders && @loaders.all?(&:run?)) end
#parent (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/associations/preloader/branch.rb', line 7
attr_reader :association, :children, :parent
#polymorphic? ⇒ Boolean
(readonly)
[ GitHub ]
# File 'activerecord/lib/active_record/associations/preloader/branch.rb', line 108
def polymorphic? return false if root? return @polymorphic if defined?(@polymorphic) @polymorphic = source_records.any? do |record| reflection = record.class._reflect_on_association(association) reflection && reflection. [:polymorphic] end end
#preloaded_records (rw)
[ GitHub ]# File 'activerecord/lib/active_record/associations/preloader/branch.rb', line 68
def preloaded_records @preloaded_records ||= loaders.flat_map(&:preloaded_records) end
#preloaded_records=(value) (rw)
[ GitHub ]# File 'activerecord/lib/active_record/associations/preloader/branch.rb', line 9
attr_writer :preloaded_records
#root? ⇒ Boolean
(readonly)
[ GitHub ]
# File 'activerecord/lib/active_record/associations/preloader/branch.rb', line 60
def root? parent.nil? end
#scope (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/associations/preloader/branch.rb', line 8
attr_reader :scope, :associate_by_default
Instance Method Details
#build_children(children) (private)
[ GitHub ]# File 'activerecord/lib/active_record/associations/preloader/branch.rb', line 126
def build_children(children) Array.wrap(children).flat_map { |association| Array(association).flat_map { |parent, child| Branch.new( parent: self, association: parent, children: child, associate_by_default: associate_by_default, scope: scope ) } } end
#future_classes
[ GitHub ]# File 'activerecord/lib/active_record/associations/preloader/branch.rb', line 27
def future_classes (immediate_future_classes + children.flat_map(&:future_classes)).uniq end
#grouped_records
[ GitHub ]# File 'activerecord/lib/active_record/associations/preloader/branch.rb', line 80
def grouped_records h = {} polymorphic_parent = !root? && parent.polymorphic? source_records.each do |record| reflection = record.class._reflect_on_association(association) next if polymorphic_parent && !reflection || !record.association(association).klass (h[reflection] ||= []) << record end h end
#immediate_future_classes
[ GitHub ]# File 'activerecord/lib/active_record/associations/preloader/branch.rb', line 31
def immediate_future_classes if parent.done? loaders.flat_map(&:future_classes).uniq else likely_reflections.reject(&:polymorphic?).flat_map do |reflection| reflection. chain. map(&:klass) end.uniq end end
#likely_reflections
[ GitHub ]# File 'activerecord/lib/active_record/associations/preloader/branch.rb', line 53
def likely_reflections parent_classes = parent.target_classes parent_classes.filter_map do |parent_klass| parent_klass._reflect_on_association(@association) end end
#loaders
[ GitHub ]# File 'activerecord/lib/active_record/associations/preloader/branch.rb', line 118
def loaders @loaders ||= grouped_records.flat_map do |reflection, reflection_records| preloaders_for_reflection(reflection, reflection_records) end end
#preloader_for(reflection) (private)
Returns a class containing the logic needed to load preload the data and attach it to a relation. The class returned implements a run
method that accepts a preloader.
# File 'activerecord/lib/active_record/associations/preloader/branch.rb', line 143
def preloader_for(reflection) if reflection. [:through] ThroughAssociation else Association end end
#preloaders_for_reflection(reflection, reflection_records)
[ GitHub ]# File 'activerecord/lib/active_record/associations/preloader/branch.rb', line 91
def preloaders_for_reflection(reflection, reflection_records) reflection_records.group_by do |record| klass = record.association(association).klass if reflection.scope && reflection.scope.arity != 0 # For instance dependent scopes, the scope is potentially # different for each record. To allow this we'll group each # object separately into its own preloader reflection_scope = reflection.join_scopes(klass.arel_table, klass.predicate_builder, klass, record).inject(&:merge!) end [klass, reflection_scope] end.map do |(rhs_klass, reflection_scope), rs| preloader_for(reflection).new(rhs_klass, rs, reflection, scope, reflection_scope, associate_by_default) end end
#runnable_loaders
[ GitHub ]# File 'activerecord/lib/active_record/associations/preloader/branch.rb', line 76
def runnable_loaders loaders.flat_map(&:runnable_loaders).reject(&:run?) end
#source_records
[ GitHub ]# File 'activerecord/lib/active_record/associations/preloader/branch.rb', line 64
def source_records @parent.preloaded_records end
#target_classes
[ GitHub ]# File 'activerecord/lib/active_record/associations/preloader/branch.rb', line 43
def target_classes if done? preloaded_records.map(&:klass).uniq elsif parent.done? loaders.map(&:klass).uniq else likely_reflections.reject(&:polymorphic?).map(&:klass).uniq end end