Class: GraphQL::RootCall

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

Overview

Every query begins with a root call. It might find data or mutate data and return some results.

A root call should:

  • declare any arguments with RootCall.argument, or declare ‘argument.none`

  • declare returns with return

  • implement #execute! to take those arguments and return values

Examples:

FindPostCall < GraphQL::RootCall
  argument.number(:ids, any_number: true)
  returns :post

  def execute!(*ids)
    ids.map { |id| Post.find(id) }
  end
end
CreateCommentCall < GraphQL::RootCall
  argument.number(:post_id)
  argument.object(:comment)
  returns :post, :comment

  def execute!(post_id, comment)
    post = Post.find(post_id)
    new_comment = post.comments.create!(comment)
    {
      comment: new_comment,
      post: post,
    }
  end
end

Constant Summary collapse

TYPE_CHECKS =
{
  "object" => Hash,
  "number" => Numeric,
  "string" => String,
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(query:, syntax_arguments:) ⇒ RootCall

Returns a new instance of RootCall.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/graphql/root_call.rb', line 37

def initialize(query:, syntax_arguments:)
  @query = query

  raise "#{self.class.name} must declare arguments" unless self.class.arguments
  @arguments = syntax_arguments.each_with_index.map do |syntax_arg, idx|

    value = if syntax_arg[0] == "<"
        query.get_variable(syntax_arg).json_string
      else
        syntax_arg
      end

    self.class.typecast(idx, value)
  end
end

Instance Attribute Details

#argumentsObject (readonly)

Returns the value of attribute arguments.



36
37
38
# File 'lib/graphql/root_call.rb', line 36

def arguments
  @arguments
end

#queryObject (readonly)

Returns the value of attribute query.



36
37
38
# File 'lib/graphql/root_call.rb', line 36

def query
  @query
end

Class Method Details

.abstract!Object

This call won’t be visible in ‘schema()`



96
97
98
# File 'lib/graphql/root_call.rb', line 96

def abstract!
  GraphQL::SCHEMA.remove_call(self)
end

.argumentGraphQL::RootCallArgumentDefiner

Use this object to declare arguments.

Returns:



127
128
129
# File 'lib/graphql/root_call.rb', line 127

def argument
  @argument ||= GraphQL::RootCallArgumentDefiner.new(self)
end

.argument_for_index(idx) ⇒ Object



142
143
144
145
146
147
148
# File 'lib/graphql/root_call.rb', line 142

def argument_for_index(idx)
  if arguments.first.any_number
    arguments.first
  else
    arguments[idx]
  end
end

.argumentsObject



135
136
137
138
139
140
# File 'lib/graphql/root_call.rb', line 135

def arguments
  own = own_arguments || []
  own + superclass.arguments
rescue NoMethodError
  own
end

.indentifier(ident_name) ⇒ Object

Declare an alternative name used in a query string

Parameters:

  • ident_name (String)


81
82
83
84
# File 'lib/graphql/root_call.rb', line 81

def indentifier(ident_name)
  @identifier = ident_name
  GraphQL::SCHEMA.add_call(self)
end

.inherited(child_class) ⇒ Object



91
92
93
# File 'lib/graphql/root_call.rb', line 91

def inherited(child_class)
  GraphQL::SCHEMA.add_call(child_class)
end

.own_argumentsObject



131
132
133
# File 'lib/graphql/root_call.rb', line 131

def own_arguments
  @argument && @argument.arguments
end

.return_declarationsObject



121
122
123
# File 'lib/graphql/root_call.rb', line 121

def return_declarations
  @return_declarations ||= {}
end

.returns(*return_declaration_names) ⇒ Object

Name of returned values from this call

Parameters:

  • return_declarations (Symbol)


102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/graphql/root_call.rb', line 102

def returns(*return_declaration_names)
  if return_declaration_names.last.is_a?(Hash)
    return_declarations_hash = return_declaration_names.pop
  else
    return_declarations_hash = {}
  end

  raise "Return keys must be symbols" if  (return_declarations.keys + return_declaration_names).any? { |k| !k.is_a?(Symbol) }

  return_declaration_names.each do |return_sym|
    return_type = return_sym.to_s
    return_declarations[return_sym] = return_type
  end

  return_declarations_hash.each do |return_sym, return_type|
    return_declarations[return_sym] = return_type
  end
end

.schema_nameObject

The name used by SCHEMA. Uses identifier or derives a name from the class name.



87
88
89
# File 'lib/graphql/root_call.rb', line 87

def schema_name
  @identifier || name.split("::").last.sub(/Call$/, '').underscore
end

.typecast(idx, value) ⇒ Object



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/graphql/root_call.rb', line 156

def typecast(idx, value)
  arg_dec = argument_for_index(idx)
  expected_type = arg_dec.type
  expected_type_class = TYPE_CHECKS[expected_type]

  if expected_type == "string"
    parsed_value = value
  else
    parsed_value = JSON.parse('{ "value" : ' + value + '}')["value"]
  end

  if !parsed_value.is_a?(expected_type_class)
    raise GraphQL::RootCallArgumentError.new(arg_dec, value)
  end

  parsed_value
rescue JSON::ParserError
  raise GraphQL::RootCallArgumentError.new(arg_dec, value)
end

Instance Method Details

#as_resultObject



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/graphql/root_call.rb', line 61

def as_result
  return_declarations = self.class.return_declarations
  raise "#{self.class.name} must declare returns" unless return_declarations.present?
  return_values = execute!(*arguments)

  if return_values.is_a?(Hash)
    unexpected_returns = return_values.keys - return_declarations.keys
    missing_returns = return_declarations.keys - return_values.keys
    if unexpected_returns.any?
      raise "#{self.class.name} returned #{unexpected_returns}, but didn't declare them."
    elsif missing_returns.any?
      raise "#{self.class.name} declared #{missing_returns}, but didn't return them."
    end
  end
  return_values
end

#contextObject



57
58
59
# File 'lib/graphql/root_call.rb', line 57

def context
  query.context
end

#execute!(*args) ⇒ Object

Raises:

  • (NotImplementedError)


53
54
55
# File 'lib/graphql/root_call.rb', line 53

def execute!(*args)
  raise NotImplementedError, "Do work in this method"
end