class GraphQL::Execution::Interpreter::ArgumentsCache

Constants

NO_ARGUMENTS
NO_VALUE_GIVEN

Public Class Methods

new(query) click to toggle source
# File lib/graphql/execution/interpreter/arguments_cache.rb, line 7
def initialize(query)
  @query = query
  @dataloader = query.context.dataloader
  @storage = Hash.new do |h, ast_node|
    h[ast_node] = Hash.new do |h2, arg_owner|
      h2[arg_owner] = Hash.new do |h3, parent_object|
        dataload_for(ast_node, arg_owner, parent_object) do |kwarg_arguments|
          h3[parent_object] = @query.schema.after_lazy(kwarg_arguments) do |resolved_args|
            h3[parent_object] = resolved_args
          end
        end

        if !h3.key?(parent_object)
          # TODO should i bother putting anything here?
          h3[parent_object] = NO_ARGUMENTS
        else
          h3[parent_object]
        end
      end
    end
  end
end

Private Class Methods

prepare_args_hash(query, ast_arg_or_hash_or_value) click to toggle source
# File lib/graphql/execution/interpreter/arguments_cache.rb, line 62
def self.prepare_args_hash(query, ast_arg_or_hash_or_value)
  case ast_arg_or_hash_or_value
  when Hash
    if ast_arg_or_hash_or_value.empty?
      return NO_ARGUMENTS
    end
    args_hash = {}
    ast_arg_or_hash_or_value.each do |k, v|
      args_hash[k] = prepare_args_hash(query, v)
    end
    args_hash
  when Array
    ast_arg_or_hash_or_value.map { |v| prepare_args_hash(query, v) }
  when GraphQL::Language::Nodes::Field, GraphQL::Language::Nodes::InputObject, GraphQL::Language::Nodes::Directive
    if ast_arg_or_hash_or_value.arguments.empty? # rubocop:disable Development/ContextIsPassedCop -- AST-related
      return NO_ARGUMENTS
    end
    args_hash = {}
    ast_arg_or_hash_or_value.arguments.each do |arg| # rubocop:disable Development/ContextIsPassedCop -- AST-related
      v = prepare_args_hash(query, arg.value)
      if v != NO_VALUE_GIVEN
        args_hash[arg.name] = v
      end
    end
    args_hash
  when GraphQL::Language::Nodes::VariableIdentifier
    if query.variables.key?(ast_arg_or_hash_or_value.name)
      variable_value = query.variables[ast_arg_or_hash_or_value.name]
      prepare_args_hash(query, variable_value)
    else
      NO_VALUE_GIVEN
    end
  when GraphQL::Language::Nodes::Enum
    ast_arg_or_hash_or_value.name
  when GraphQL::Language::Nodes::NullValue
    nil
  else
    ast_arg_or_hash_or_value
  end
end

Public Instance Methods

dataload_for(ast_node, argument_owner, parent_object, &block) click to toggle source

@yield [Interpreter::Arguments, Lazy<Interpreter::Arguments>] The finally-loaded arguments

# File lib/graphql/execution/interpreter/arguments_cache.rb, line 49
def dataload_for(ast_node, argument_owner, parent_object, &block)
  # First, normalize all AST or Ruby values to a plain Ruby hash
  args_hash = self.class.prepare_args_hash(@query, ast_node)
  argument_owner.coerce_arguments(parent_object, args_hash, @query.context, &block)
  nil
end
fetch(ast_node, argument_owner, parent_object) click to toggle source
# File lib/graphql/execution/interpreter/arguments_cache.rb, line 30
def fetch(ast_node, argument_owner, parent_object)
  # If any jobs were enqueued, run them now,
  # since this might have been called outside of execution.
  # (The jobs are responsible for updating `result` in-place.)
  if !@storage.key?(ast_node) || !@storage[ast_node].key?(argument_owner)
    @dataloader.run_isolated do
      @storage[ast_node][argument_owner][parent_object]
    end
  end
  # Ack, the _hash_ is updated, but the key is eventually
  # overridden with an immutable arguments instance.
  # The first call queues up the job,
  # then this call fetches the result.
  # TODO this should be better, find a solution
  # that works with merging the runtime.rb code
  @storage[ast_node][argument_owner][parent_object]
end