class GraphQL::InputObjectType

{InputObjectType}s are key-value inputs for fields.

Input objects have arguments which are identical to {GraphQL::Field} arguments. They map names to types and support default values. Their input types can be any input types, including {InputObjectType}s.

@example An input type with name and number

PlayerInput = GraphQL::InputObjectType.define do
  name("Player")
  argument :name, !types.String
  argument :number, !types.Int
end

In a `resolve` function, you can access the values by making nested lookups on `args`.

@example Accessing input values in a resolve function

resolve ->(obj, args, ctx) {
  args[:player][:name]    # => "Tony Gwynn"
  args[:player][:number]  # => 19
  args[:player].to_h      # { "name" => "Tony Gwynn", "number" => 19 }
  # ...
}

Constants

INVALID_OBJECT_MESSAGE

@api private

Attributes

arguments[RW]
arguments_class[RW]
input_fields[RW]
mutation[RW]

Public Class Methods

new() click to toggle source

@!attribute arguments @return [Hash<String => GraphQL::Argument>] Map String argument names to their {GraphQL::Argument} implementations

Calls superclass method GraphQL::BaseType.new
# File lib/graphql/input_object_type.rb, line 43
def initialize
  super
  @arguments = {}
end

Public Instance Methods

coerce_result(value, ctx = nil) click to toggle source
# File lib/graphql/input_object_type.rb, line 57
def coerce_result(value, ctx = nil)
  if ctx.nil?
    warn_deprecated_coerce("coerce_isolated_result")
    ctx = GraphQL::Query::NullContext
  end

  # Allow the application to provide values as :symbols, and convert them to the strings
  value = value.reduce({}) { |memo, (k, v)| memo[k.to_s] = v; memo }

  result = {}

  arguments.each do |input_key, input_field_defn|
    input_value = value[input_key]
    if value.key?(input_key)
      result[input_key] = if input_value.nil?
        nil
      else
        input_field_defn.type.coerce_result(input_value, ctx)
      end
    end
  end

  result
end
initialize_copy(other) click to toggle source
Calls superclass method GraphQL::BaseType#initialize_copy
# File lib/graphql/input_object_type.rb, line 48
def initialize_copy(other)
  super
  @arguments = other.arguments.dup
end
kind() click to toggle source
# File lib/graphql/input_object_type.rb, line 53
def kind
  GraphQL::TypeKinds::INPUT_OBJECT
end

Private Instance Methods

coerce_non_null_input(value, ctx) click to toggle source
# File lib/graphql/input_object_type.rb, line 84
def coerce_non_null_input(value, ctx)
  input_values = {}
  defaults_used = Set.new

  arguments.each do |input_key, input_field_defn|
    field_value = value[input_key]

    if value.key?(input_key)
      coerced_value = input_field_defn.type.coerce_input(field_value, ctx)
      input_values[input_key] = input_field_defn.prepare(coerced_value, ctx)
    elsif input_field_defn.default_value?
      input_values[input_key] = input_field_defn.default_value
      defaults_used << input_key
    end
  end

  arguments_class.new(input_values, context: ctx, defaults_used: defaults_used)
end
validate_non_null_input(input, ctx) click to toggle source
# File lib/graphql/input_object_type.rb, line 106
def validate_non_null_input(input, ctx)
  warden = ctx.warden
  result = GraphQL::Query::InputValidationResult.new

  if input.is_a?(Array)
    result.add_problem(INVALID_OBJECT_MESSAGE % { object: JSON.generate(input, quirks_mode: true) })
    return result
  end

  # We're not actually _using_ the coerced result, we're just
  # using these methods to make sure that the object will
  # behave like a hash below, when we call `each` on it.
  begin
    input.to_h
  rescue
    begin
      # Handle ActionController::Parameters:
      input.to_unsafe_h
    rescue
      # We're not sure it'll act like a hash, so reject it:
      result.add_problem(INVALID_OBJECT_MESSAGE % { object: JSON.generate(input, quirks_mode: true) })
      return result
    end
  end

  visible_arguments_map = warden.arguments(self).reduce({}) { |m, f| m[f.name] = f; m}

  # Items in the input that are unexpected
  input.each do |name, value|
    if visible_arguments_map[name].nil?
      result.add_problem("Field is not defined on #{self.name}", [name])
    end
  end

  # Items in the input that are expected, but have invalid values
  visible_arguments_map.map do |name, field|
    field_result = field.type.validate_input(input[name], ctx)
    if !field_result.valid?
      result.merge_result!(name, field_result)
    end
  end

  result
end