class GraphQL::Query::LiteralInput

Turn query string values into something useful for query execution

def self.coerce(type, ast_node, variables)

def self.coerce(type, ast_node, variables)
  case ast_node
  when nil
    nil
  when Language::Nodes::NullValue
    nil
  when Language::Nodes::VariableIdentifier
    variables[ast_node.name]
  else
    case type.kind.name
    when "SCALAR"
      # TODO smell
      # This gets used for plain values during subscriber.trigger
      if variables
        type.coerce_input(ast_node, variables.context)
      else
        type.coerce_isolated_input(ast_node)
      end
    when "ENUM"
      # TODO smell
      # This gets used for plain values sometimes
      v = ast_node.is_a?(GraphQL::Language::Nodes::Enum) ? ast_node.name : ast_node
      if variables
        type.coerce_input(v, variables.context)
      else
        type.coerce_isolated_input(v)
      end
    when "NON_NULL"
      LiteralInput.coerce(type.of_type, ast_node, variables)
    when "LIST"
      if ast_node.is_a?(Array)
        ast_node.map { |element_ast| LiteralInput.coerce(type.of_type, element_ast, variables) }
      else
        [LiteralInput.coerce(type.of_type, ast_node, variables)]
      end
    when "INPUT_OBJECT"
      # TODO smell: handling AST vs handling plain Ruby
      next_args = ast_node.is_a?(Hash) ? ast_node : ast_node.arguments
      from_arguments(next_args, type, variables)
    else
      raise "Invariant: unexpected type to coerce to: #{type}"
    end
  end
end

def self.from_arguments(ast_arguments, argument_owner, variables)

def self.from_arguments(ast_arguments, argument_owner, variables)
  context = variables ? variables.context : nil
  values_hash = {}
  defaults_used = Set.new
  indexed_arguments = case ast_arguments
  when Hash
    ast_arguments
  when Array
    ast_arguments.each_with_object({}) { |a, memo| memo[a.name] = a }
  else
    raise ArgumentError, "Unexpected ast_arguments: #{ast_arguments}"
  end
  argument_defns = argument_owner.arguments
  argument_defns.each do |arg_name, arg_defn|
    ast_arg = indexed_arguments[arg_name]
    # First, check the argument in the AST.
    # If the value is a variable,
    # only add a value if the variable is actually present.
    # Otherwise, coerce the value in the AST, prepare the value and add it.
    #
    # TODO: since indexed_arguments can come from a plain Ruby hash,
    # have to check for `false` or `nil` as hash values. This is getting smelly :S
    if indexed_arguments.key?(arg_name)
      arg_value = ast_arg.is_a?(GraphQL::Language::Nodes::Argument) ? ast_arg.value : ast_arg
      value_is_a_variable = arg_value.is_a?(GraphQL::Language::Nodes::VariableIdentifier)
      if (!value_is_a_variable || (value_is_a_variable && variables.key?(arg_value.name)))
        value = coerce(arg_defn.type, arg_value, variables)
        # Legacy `prepare` application
        if arg_defn.is_a?(GraphQL::Argument)
          value = arg_defn.prepare(value, context)
        end
        if value.is_a?(GraphQL::ExecutionError)
          value.ast_node = ast_arg
          raise value
        end
        values_hash[arg_name] = value
      end
    end
    # Then, the definition for a default value.
    # If the definition has a default value and
    # a value wasn't provided from the AST,
    # then add the default value.
    if arg_defn.default_value? && !values_hash.key?(arg_name)
      value = arg_defn.default_value
      defaults_used << arg_name
      # `context` isn't present when pre-calculating defaults
      if context
        if arg_defn.is_a?(GraphQL::Argument)
          value = arg_defn.prepare(value, context)
        end
        if value.is_a?(GraphQL::ExecutionError)
          value.ast_node = ast_arg
          raise value
        end
      end
      values_hash[arg_name] = value
    end
  end
  if argument_owner.is_a?(Class) || argument_owner.is_a?(GraphQL::Schema::Field)
    # A Schema::InputObject, Schema::GraphQL::Field, Schema::Directive, logic from Query::Arguments#to_kwargs
    ruby_kwargs = {}
    values_hash.each do |key, value|
      ruby_kwargs[Schema::Member::BuildType.underscore(key).to_sym] = value
    end
    if argument_owner.is_a?(Class) && argument_owner < GraphQL::Schema::InputObject
      argument_owner.new(ruby_kwargs: ruby_kwargs, context: context, defaults_used: defaults_used)
    else
      ruby_kwargs
    end
  else
    result = argument_owner.arguments_class.new(values_hash, context: context, defaults_used: defaults_used)
    result.prepare
  end
end