Sha256: b66562080feac9712b24400c4403f530207d1b8d8d7ec6495e1d87424912914d

Contents?: true

Size: 1.96 KB

Versions: 1

Compression:

Stored size: 1.96 KB

Contents

module GraphQL
  module Preload
    # Provides an instrument for the GraphQL::Field :preload definition
    class Instrument
      def instrument(_type, field)
        return field unless field.metadata.include?(:preload)

        old_resolver = field.resolve_proc
        new_resolver = ->(obj, args, ctx) do
          return old_resolver.call(obj, args, ctx) unless obj

          preload(obj, field.metadata[:preload]).then do
            old_resolver.call(obj, args, ctx)
          end
        end

        field.redefine do
          resolve(new_resolver)
        end
      end

      private def preload(record, associations)
        return preload_single_association(record, associations) if associations.is_a?(Symbol)

        promises = []

        Array.wrap(associations).each do |association|
          case association
          when Symbol
            promises << preload_single_association(record, association)
          when Array
            association.each do |sub_association|
              promises << preload(record, sub_association)
            end
          when Hash
            association.each do |sub_association, nested_association|
              promises << preload_single_association(record, sub_association).then do
                associated_records = record.public_send(sub_association)

                case associated_records
                when ActiveRecord::Base
                  preload(associated_records, nested_association)
                else
                  Promise.all(
                    Array.wrap(associated_records).map do |associated_record|
                      preload(associated_record, nested_association)
                    end
                  )
                end
              end
            end
          end
        end

        Promise.all(promises)
      end

      private def preload_single_association(record, association)
        GraphQL::Preload::Loader.for(record.class, association).load(record)
      end
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
graphql-preload-1.0.3 lib/graphql/preload/instrument.rb