class GraphQL::Preload::Loader

Preloads ActiveRecord::Associations when called from the Preload::Instrument

Attributes

association[R]
model[R]
scope[RW]

Public Class Methods

new(model, association, _scope_sql) click to toggle source
# File lib/graphql/preload/loader.rb, line 12
def initialize(model, association, _scope_sql)
  @association = association
  @model = model

  validate_association
end

Public Instance Methods

cache_key(record) click to toggle source
# File lib/graphql/preload/loader.rb, line 8
def cache_key(record)
  record.object_id
end
load(record) click to toggle source
Calls superclass method
# File lib/graphql/preload/loader.rb, line 19
def load(record)
  unless record.is_a?(model)
    raise TypeError, "Loader for #{model} can't load associations for #{record.class} objects"
  end

  return Promise.resolve(record) if association_loaded?(record)
  super
end
perform(records) click to toggle source
# File lib/graphql/preload/loader.rb, line 28
def perform(records)
  preload_association(records)
  records.each { |record| fulfill(record, record) }
end

Private Instance Methods

association_loaded?(record) click to toggle source
# File lib/graphql/preload/loader.rb, line 33
        def association_loaded?(record)
  record.association(association).loaded?
end
preload_association(records) click to toggle source
# File lib/graphql/preload/loader.rb, line 37
        def preload_association(records)
  preloader = ActiveRecord::Associations::Preloader.new.preload(records, association, preload_scope).first
  return unless preload_scope
  return if Gem::Version.new(ActiveRecord::VERSION::STRING) < Gem::Version.new("6.0.0")

  if preloader.is_a?(::ActiveRecord::Associations::Preloader::AlreadyLoaded)
    raise ArgumentError,
        "Preloading association twice with scopes is not possible. " \
        "To resolve this problem add a scoped association (e.g., `has_many :records, -> { scope_name }, ...`) to the model"
  end

  # this commit changes the way preloader works with scopes
  # https://github.com/rails/rails/commit/2847653869ffc1ff5139c46e520c72e26618c199#diff-3bba5f66eb1ed62bd5700872fcd6c632
  preloader.send(:owners).each do |owner|
    preloader.send(:associate_records_to_owner, owner, preloader.records_by_owner[owner] || [])
  end
end
preload_scope() click to toggle source
# File lib/graphql/preload/loader.rb, line 55
        def preload_scope
  return nil unless scope
  reflection = model.reflect_on_association(association)
  raise ArgumentError, 'Cannot specify preload_scope for polymorphic associations' if reflection.polymorphic?
  scope if scope.try(:klass) == reflection.klass
end
validate_association() click to toggle source
# File lib/graphql/preload/loader.rb, line 62
        def validate_association
  unless association.is_a?(Symbol)
    raise ArgumentError, 'Association must be a Symbol object'
  end

  unless model < ActiveRecord::Base
    raise ArgumentError, 'Model must be an ActiveRecord::Base descendant'
  end

  return if model.reflect_on_association(association)
  raise TypeError, "Association :#{association} does not exist on #{model}"
end