Class: GraphQL::Schema::Resolver Private

Inherits:
Object
  • Object
show all
Extended by:
Member::BaseDSLMethods, Member::HasArguments
Includes:
Member::GraphQLTypeNames
Defined in:
lib/graphql/schema/resolver.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

A class-based container for field configuration and resolution logic. It supports:

  • Arguments, via .argument(...) helper, which will be applied to the field.
  • Return type, via .type(..., null: ...), which will be applied to the field.
  • Description, via .description(...), which will be applied to the field
  • Resolution, via #resolve(**args) method, which will be called to resolve the field.
  • #object and #context accessors for use during #resolve.

Resolvers can be attached with the resolver: option in a field(...) call.

A resolver’s configuration may be overridden with other keywords in the field(...) call.

See the Resolver.field_options to see how a Resolver becomes a set of field configuration options.

See Also:

  • for a concrete subclass of `Resolver`.
  • `Resolver` is a replacement for `GraphQL::Function`

Direct Known Subclasses

Mutation

Defined Under Namespace

Classes: LoadApplicationObjectFailedError

Constant Summary

Constants included from Member::GraphQLTypeNames

Member::GraphQLTypeNames::Boolean, Member::GraphQLTypeNames::ID, Member::GraphQLTypeNames::Int

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Member::HasArguments

argument, argument_class, arguments, own_arguments

Methods included from Member::BaseDSLMethods

accessible?, authorized?, description, graphql_name, introspection, mutation, name, overridden_graphql_name, to_graphql, visible?

Constructor Details

#initialize(object:, context:) ⇒ Resolver

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of Resolver

Parameters:



29
30
31
32
33
34
35
36
37
38
# File 'lib/graphql/schema/resolver.rb', line 29

def initialize(object:, context:)
  @object = object
  @context = context
  # Since this hash is constantly rebuilt, cache it for this call
  @arguments_by_keyword = {}
  self.class.arguments.each do |name, arg|
    @arguments_by_keyword[arg.keyword] = arg
  end
  @arguments_loads_as_type = self.class.arguments_loads_as_type
end

Instance Attribute Details

#contextGraphQL::Query::Context (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



44
45
46
# File 'lib/graphql/schema/resolver.rb', line 44

def context
  @context
end

#objectObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns The application object this field is being resolved on

Returns:

  • (Object)

    The application object this field is being resolved on



41
42
43
# File 'lib/graphql/schema/resolver.rb', line 41

def object
  @object
end

Class Method Details

.argument(name, type, *rest, loads: nil, **kwargs, &block) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Add an argument to this field’s signature, but also add some preparation hook methods which will be used for this argument

See Also:

  • for the signature


296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
# File 'lib/graphql/schema/resolver.rb', line 296

def argument(name, type, *rest, loads: nil, **kwargs, &block)
  if loads
    arg_keyword = name.to_s.sub(/_id$/, "").to_sym
    kwargs[:as] = arg_keyword
    own_arguments_loads_as_type[arg_keyword] = loads
  end
  arg_defn = super(name, type, *rest, **kwargs, &block)

  if loads
    class_eval <<-RUBY, __FILE__, __LINE__ + 1
    def load_#{arg_defn.keyword}(value)
      load_application_object(:#{arg_defn.keyword}, value)
    end
    RUBY
  else
    class_eval <<-RUBY, __FILE__, __LINE__ + 1
    def load_#{arg_defn.keyword}(value)
      value
    end
    RUBY
  end

  class_eval <<-RUBY, __FILE__, __LINE__ + 1
  def validate_#{arg_defn.keyword}(value)
    # No-op
  end
  RUBY
  arg_defn
end

.arguments_loads_as_typeObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



327
328
329
330
# File 'lib/graphql/schema/resolver.rb', line 327

def arguments_loads_as_type
  inherited_lookups = superclass.respond_to?(:arguments_loads_as_type) ? superclass.arguments_loads_as_type : {}
  inherited_lookups.merge(own_arguments_loads_as_type)
end

.complexity(new_complexity = nil) ⇒ Integer, Proc

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Specifies the complexity of the field. Defaults to 1

Returns:

  • (Integer, Proc)


268
269
270
271
272
273
# File 'lib/graphql/schema/resolver.rb', line 268

def complexity(new_complexity = nil)
  if new_complexity
    @complexity = new_complexity
  end
  @complexity || (superclass.respond_to?(:complexity) ? superclass.complexity : 1)
end

.extras(new_extras = nil) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Additional info injected into #resolve

See Also:

  • {GraphQL{GraphQL::Schema{GraphQL::Schema::Field{GraphQL::Schema::Field#extras}


222
223
224
225
226
227
228
# File 'lib/graphql/schema/resolver.rb', line 222

def extras(new_extras = nil)
  if new_extras
    @own_extras = new_extras
  end
  own_extras = @own_extras || []
  own_extras + (superclass.respond_to?(:extras) ? superclass.extras : [])
end

.field_optionsObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



275
276
277
278
279
280
281
282
283
284
285
286
# File 'lib/graphql/schema/resolver.rb', line 275

def field_options
  {
    type: type_expr,
    description: description,
    extras: extras,
    method: :resolve_with_support,
    resolver_class: self,
    arguments: arguments,
    null: null,
    complexity: complexity,
  }
end

.null(allow_null = nil) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Specifies whether or not the field is nullable. Defaults to true TODO unify with #type

Parameters:

  • allow_null (Boolean) (defaults to: nil)

    Whether or not the response can be null



233
234
235
236
237
238
239
# File 'lib/graphql/schema/resolver.rb', line 233

def null(allow_null = nil)
  if !allow_null.nil?
    @null = allow_null
  end

  @null.nil? ? (superclass.respond_to?(:null) ? superclass.null : true) : @null
end

.resolve_method(new_method = nil) ⇒ Symbol

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Default :resolve set below.

Returns:

  • (Symbol)

    The method to call on instances of this object to resolve the field



213
214
215
216
217
218
# File 'lib/graphql/schema/resolver.rb', line 213

def resolve_method(new_method = nil)
  if new_method
    @resolve_method = new_method
  end
  @resolve_method || (superclass.respond_to?(:resolve_method) ? superclass.resolve_method : :resolve)
end

.type(new_type = nil, null: nil) ⇒ Class

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Call this method to get the return type of the field, or use it as a configuration method to assign a return type instead of generating one. TODO unify with #null

Parameters:

  • new_type (Class, nil) (defaults to: nil)

    If a type definition class is provided, it will be used as the return type of the field

  • null (true, false)

    Whether or not the field may return nil

Returns:

  • (Class)

    The type which this field returns.



248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/graphql/schema/resolver.rb', line 248

def type(new_type = nil, null: nil)
  if new_type
    if null.nil?
      raise ArgumentError, "required argument `null:` is missing"
    end
    @type_expr = new_type
    @null = null
  else
    if @type_expr
      GraphQL::Schema::Member::BuildType.parse_type(@type_expr, null: @null)
    elsif superclass.respond_to?(:type)
      superclass.type
    else
      nil
    end
  end
end

.type_exprObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

A non-normalized type configuration, without null applied



289
290
291
# File 'lib/graphql/schema/resolver.rb', line 289

def type_expr
  @type_expr || (superclass.respond_to?(:type_expr) ? superclass.type_expr : nil)
end

Instance Method Details

#before_prepare(**args) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Called before arguments are prepared. Implement this hook to make checks before doing any work.

If it returns a lazy object (like a promise), it will be synced by GraphQL (but the resulting value won’t be used).

Parameters:

  • args (Hash)

    The input arguments, if there are any

Raises:



91
92
# File 'lib/graphql/schema/resolver.rb', line 91

def before_prepare(**args)
end

#resolve(**args) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Do the work. Everything happens here.

Returns:

  • (Object)

    An object corresponding to the return type

Raises:

  • (NotImplementedError)


78
79
80
# File 'lib/graphql/schema/resolver.rb', line 78

def resolve(**args)
  raise NotImplementedError, "#{self.class.name}#resolve should execute the field's logic"
end

#resolve_with_support(**args) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method is actually called by the runtime, it does some preparation and then eventually calls the user-defined #resolve method.



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
# File 'lib/graphql/schema/resolver.rb', line 50

def resolve_with_support(**args)
  # First call the before_prepare hook which may raise
  before_prepare_val = if args.any?
    before_prepare(**args)
  else
    before_prepare
  end
  context.schema.after_lazy(before_prepare_val) do
    # Then call each prepare hook, which may return a different value
    # for that argument, or may return a lazy object
    load_arguments_val = load_arguments(args)
    context.schema.after_lazy(load_arguments_val) do |loaded_args|
      # Then validate each argument, which may raise or may return a lazy object
      validate_arguments_val = validate_arguments(loaded_args)
      context.schema.after_lazy(validate_arguments_val) do |validated_args|
        # Finally, all the hooks have passed, so resolve it
        if validated_args.any?
          public_send(self.class.resolve_method, **validated_args)
        else
          public_send(self.class.resolve_method)
        end
      end
    end
  end
end