Skip to content

Instantly share code, notes, and snippets.

@mmmries
Created June 2, 2020 23:41
Show Gist options
  • Save mmmries/e8fd25daea1525ea002caeb4cef0a571 to your computer and use it in GitHub Desktop.
Save mmmries/e8fd25daea1525ea002caeb4cef0a571 to your computer and use it in GitHub Desktop.
Association Loader for ruby-graphql
# from https://github.com/Shopify/graphql-batch/blob/c84a5236ecb1c38fa275c76ee38017f30b7074be/examples/association_loader.rb
# This handles creating generic association loaders (see team_member_graph.rb for an example)
class AssociationLoader < GraphQL::Batch::Loader
def self.validate(model, association_name)
new(model, association_name)
nil
end
def initialize(model, association_name)
@model = model
@association_name = association_name
validate
end
def load(record)
raise TypeError, "#{@model} loader can't load association for #{record.class}" unless record.is_a?(@model)
return Promise.resolve(read_association(record)) if association_loaded?(record)
super
end
# We want to load the associations on all records, even if they have the same id
def cache_key(record)
record.object_id
end
def perform(records)
preload_association(records)
records.each { |record| fulfill(record, read_association(record)) }
end
private
def validate
raise ArgumentError, "No association #{@association_name} on #{@model}" unless @model.reflect_on_association(@association_name)
end
def preload_association(records)
::ActiveRecord::Associations::Preloader.new.preload(records, @association_name)
end
def read_association(record)
record.public_send(@association_name)
end
def association_loaded?(record)
record.association(@association_name).loaded?
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment