Repository URL to install this package:
|
Version:
1.8.2 ▾
|
# frozen_string_literal: true
module GraphQL
class Schema
# 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 {.field_options} to see how a Resolver becomes a set of field configuration options.
#
# @see {GraphQL::Schema::Mutation} for a concrete subclass of `Resolver`.
# @see {GraphQL::Function} `Resolver` is a replacement for `GraphQL::Function`
class Resolver
include Schema::Member::GraphQLTypeNames
# Really we only need description from here, but:
extend Schema::Member::BaseDSLMethods
extend GraphQL::Schema::Member::HasArguments
# @param object [Object] the initialize object, pass to {Query.initialize} as `root_value`
# @param context [GraphQL::Query::Context]
def initialize(object:, context:)
@object = object
@context = context
end
# @return [Object] The application object this field is being resolved on
attr_reader :object
# @return [GraphQL::Query::Context]
attr_reader :context
# Do the work. Everything happens here.
# @return [Object] An object corresponding to the return type
def resolve(**args)
raise NotImplementedError, "#{self.class.name}#resolve should execute the field's logic"
end
class << self
# Default `:resolve` set below.
# @return [Symbol] The method to call on instances of this object to resolve the field
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
# Additional info injected into {#resolve}
# @see {GraphQL::Schema::Field#extras}
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
# Specifies whether or not the field is nullable. Defaults to `true`
# TODO unify with {#type}
# @param allow_null [Boolean] Whether or not the response can be null
def null(allow_null = nil)
if !allow_null.nil?
@null = allow_null
end
@null.nil? ? (superclass.respond_to?(:null) ? superclass.null : true) : @null
end
# 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}
# @param new_type [Class, nil] If a type definition class is provided, it will be used as the return type of the field
# @param null [true, false] Whether or not the field may return `nil`
# @return [Class] The type which this field returns.
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
def field_options
{
type: type_expr,
description: description,
extras: extras,
method: resolve_method,
resolver_class: self,
arguments: arguments,
null: null,
}
end
# A non-normalized type configuration, without `null` applied
def type_expr
@type_expr || (superclass.respond_to?(:type_expr) ? superclass.type_expr : nil)
end
end
end
end
end