Class: GraphQL::Query::LiteralInput

Inherits:
Object
  • Object
show all
Defined in:
lib/graphql/query/literal_input.rb

Overview

Turn query string values into something useful for query execution

Class Method Summary collapse

Class Method Details

.coerce(type, ast_node, variables) ⇒ Object


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/graphql/query/literal_input.rb', line 6

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
    when GraphQL::ScalarType      # 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 GraphQL::EnumType      # 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 GraphQL::NonNullType
      LiteralInput.coerce(type.of_type, ast_node, variables)
    when GraphQL::ListType
      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 GraphQL::InputObjectType      # 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)
    end
  end
end

.from_arguments(ast_arguments, argument_owner, variables) ⇒ Object


49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/graphql/query/literal_input.rb', line 49

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)
        value = arg_defn.prepare(value, context)

        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
        value = arg_defn.prepare(value, context)
        if value.is_a?(GraphQL::ExecutionError)
          value.ast_node = ast_arg
          raise value
        end
      end
      values_hash[arg_name] = value
    end
  end

  argument_owner.arguments_class.new(values_hash, defaults_used)
end