Class: GraphQL::Schema::Resolver
- Inherits:
 - 
      Object
      
        
- Object
 - GraphQL::Schema::Resolver
 
 
- Extended by:
 - Member::BaseDSLMethods, Member::HasArguments, Member::HasPath
 
- Includes:
 - Member::GraphQLTypeNames, Member::HasPath
 
- Defined in:
 - lib/graphql/schema/resolver.rb,
lib/graphql/schema/resolver/has_payload_type.rb 
Overview
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. #objectand#contextaccessors 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.
Direct Known Subclasses
Defined Under Namespace
Modules: HasPayloadType
Constant Summary
Constants included from Member::GraphQLTypeNames
Member::GraphQLTypeNames::Boolean, Member::GraphQLTypeNames::ID, Member::GraphQLTypeNames::Int
Instance Attribute Summary collapse
- 
  
    
      #context  ⇒ GraphQL::Query::Context 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    
 - 
  
    
      #field  ⇒ GraphQL::Schema::Field 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    
 - 
  
    
      #object  ⇒ Object 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    
The application object this field is being resolved on.
 
Class Method Summary collapse
- 
  
    
      .argument(*args, **kwargs, &block)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Add an argument to this field’s signature, but also add some preparation hook methods which will be used for this argument.
 - 
  
    
      .arguments_loads_as_type  ⇒ Object 
    
    
  
  
  
  
  
  
  
  private
  
    
 - 
  
    
      .broadcastable(new_broadcastable)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
 - 
  
    
      .broadcastable?  ⇒ Boolean? 
    
    
  
  
  
  
  
  
  
  
  
    
 - 
  
    
      .complexity(new_complexity = nil)  ⇒ Integer, Proc 
    
    
  
  
  
  
  
  
  
  
  
    
Specifies the complexity of the field.
 - 
  
    
      .extension(extension, **options)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Registers new extension.
 - 
  
    
      .extensions  ⇒ Object 
    
    
  
  
  
  
  
  
  
  private
  
    
 - 
  
    
      .extras(new_extras = nil)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Additional info injected into #resolve.
 - 
  
    
      .field_options  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
 - 
  
    
      .null(allow_null = nil)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Specifies whether or not the field is nullable.
 - 
  
    
      .resolve_method(new_method = nil)  ⇒ Symbol 
    
    
  
  
  
  
  
  
  
  
  
    
Default
:resolveset below. - 
  
    
      .type(new_type = nil, null: nil)  ⇒ Class 
    
    
  
  
  
  
  
  
  
  
  
    
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.
 - 
  
    
      .type_expr  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
A non-normalized type configuration, without
nullapplied. 
Instance Method Summary collapse
- 
  
    
      #authorized?(**inputs)  ⇒ Boolean, early_return_data 
    
    
  
  
  
  
  
  
  
  
  
    
Called after arguments are loaded, but before resolving.
 - 
  
    
      #initialize(object:, context:, field:)  ⇒ Resolver 
    
    
  
  
  
    constructor
  
  
  
  
  
  
  
    
A new instance of Resolver.
 - 
  
    
      #ready?(**args)  ⇒ Boolean, early_return_data 
    
    
  
  
  
  
  
  
  
  
  
    
Called before arguments are prepared.
 - 
  
    
      #resolve(**args)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Do the work.
 - 
  
    
      #resolve_with_support(**args)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  private
  
    
This method is actually called by the runtime, it does some preparation and then eventually calls the user-defined
#resolvemethod. 
Methods included from Member::HasPath
Methods included from Member::HasArguments
add_argument, argument, argument_class, arguments, arguments_statically_coercible?, coerce_arguments, get_argument, own_arguments
Methods included from Member::BaseDSLMethods
accessible?, default_graphql_name, description, graphql_name, introspection, introspection?, mutation, name, overridden_graphql_name, to_graphql, visible?
Constructor Details
#initialize(object:, context:, field:) ⇒ Resolver
Returns a new instance of Resolver.
      33 34 35 36 37 38 39 40 41 42 43  | 
    
      # File 'lib/graphql/schema/resolver.rb', line 33 def initialize(object:, context:, field:) @object = object @context = context @field = field # 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
#context ⇒ GraphQL::Query::Context (readonly)
      49 50 51  | 
    
      # File 'lib/graphql/schema/resolver.rb', line 49 def context @context end  | 
  
#field ⇒ GraphQL::Schema::Field (readonly)
      52 53 54  | 
    
      # File 'lib/graphql/schema/resolver.rb', line 52 def field @field end  | 
  
#object ⇒ Object (readonly)
Returns The application object this field is being resolved on.
      46 47 48  | 
    
      # File 'lib/graphql/schema/resolver.rb', line 46 def object @object end  | 
  
Class Method Details
.argument(*args, **kwargs, &block) ⇒ Object
Add an argument to this field’s signature, but also add some preparation hook methods which will be used for this argument
      289 290 291 292 293 294 295 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  | 
    
      # File 'lib/graphql/schema/resolver.rb', line 289 def argument(*args, **kwargs, &block) loads = kwargs[:loads] # Use `from_resolver: true` to short-circuit the InputObject's own `loads:` implementation # so that we can support `#load_{x}` methods below. arg_defn = super(*args, from_resolver: true, **kwargs) own_arguments_loads_as_type[arg_defn.keyword] = loads if loads if loads && arg_defn.type.list? class_eval <<-RUBY, __FILE__, __LINE__ + 1 def load_#{arg_defn.keyword}(values) argument = @arguments_by_keyword[:#{arg_defn.keyword}] lookup_as_type = @arguments_loads_as_type[:#{arg_defn.keyword}] context.schema.after_lazy(values) do |values2| GraphQL::Execution::Lazy.all(values2.map { |value| load_application_object(argument, lookup_as_type, value, context) }) end end RUBY elsif loads class_eval <<-RUBY, __FILE__, __LINE__ + 1 def load_#{arg_defn.keyword}(value) argument = @arguments_by_keyword[:#{arg_defn.keyword}] lookup_as_type = @arguments_loads_as_type[:#{arg_defn.keyword}] load_application_object(argument, lookup_as_type, value, context) end RUBY else class_eval <<-RUBY, __FILE__, __LINE__ + 1 def load_#{arg_defn.keyword}(value) value end RUBY end arg_defn end  | 
  
.arguments_loads_as_type ⇒ 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.
      326 327 328 329  | 
    
      # File 'lib/graphql/schema/resolver.rb', line 326 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  | 
  
.broadcastable(new_broadcastable) ⇒ Object
      253 254 255  | 
    
      # File 'lib/graphql/schema/resolver.rb', line 253 def broadcastable(new_broadcastable) @broadcastable = new_broadcastable end  | 
  
.broadcastable? ⇒ Boolean?
      258 259 260 261 262 263 264  | 
    
      # File 'lib/graphql/schema/resolver.rb', line 258 def broadcastable? if defined?(@broadcastable) @broadcastable else (superclass.respond_to?(:broadcastable?) ? superclass.broadcastable? : nil) end end  | 
  
.complexity(new_complexity = nil) ⇒ Integer, Proc
Specifies the complexity of the field. Defaults to 1
      246 247 248 249 250 251  | 
    
      # File 'lib/graphql/schema/resolver.rb', line 246 def complexity(new_complexity = nil) if new_complexity @complexity = new_complexity end @complexity || (superclass.respond_to?(:complexity) ? superclass.complexity : 1) end  | 
  
.extension(extension, **options) ⇒ Object
Registers new extension
      334 335 336  | 
    
      # File 'lib/graphql/schema/resolver.rb', line 334 def extension(extension, **) extensions << {extension => } end  | 
  
.extensions ⇒ 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.
      339 340 341  | 
    
      # File 'lib/graphql/schema/resolver.rb', line 339 def extensions @extensions ||= [] end  | 
  
.extras(new_extras = nil) ⇒ Object
Additional info injected into #resolve
      200 201 202 203 204 205 206  | 
    
      # File 'lib/graphql/schema/resolver.rb', line 200 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_options ⇒ Object
      266 267 268 269 270 271 272 273 274 275 276 277 278 279  | 
    
      # File 'lib/graphql/schema/resolver.rb', line 266 def { type: type_expr, description: description, extras: extras, resolver_method: :resolve_with_support, resolver_class: self, arguments: arguments, null: null, complexity: complexity, extensions: extensions, broadcastable: broadcastable?, } end  | 
  
.null(allow_null = nil) ⇒ Object
Specifies whether or not the field is nullable. Defaults to true
TODO unify with #type
      211 212 213 214 215 216 217  | 
    
      # File 'lib/graphql/schema/resolver.rb', line 211 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
Default :resolve set below.
      191 192 193 194 195 196  | 
    
      # File 'lib/graphql/schema/resolver.rb', line 191 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
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
      226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242  | 
    
      # File 'lib/graphql/schema/resolver.rb', line 226 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_expr ⇒ Object
A non-normalized type configuration, without null applied
      282 283 284  | 
    
      # File 'lib/graphql/schema/resolver.rb', line 282 def type_expr @type_expr || (superclass.respond_to?(:type_expr) ? superclass.type_expr : nil) end  | 
  
Instance Method Details
#authorized?(**inputs) ⇒ Boolean, early_return_data
Called after arguments are loaded, but before resolving.
Override it to check everything before calling the mutation.
      135 136 137 138 139 140 141 142 143 144 145 146 147 148 149  | 
    
      # File 'lib/graphql/schema/resolver.rb', line 135 def (**inputs) self.class.arguments.each_value do |argument| arg_keyword = argument.keyword if inputs.key?(arg_keyword) && !(arg_value = inputs[arg_keyword]).nil? && (arg_value != argument.default_value) arg_auth, err = argument.(self, arg_value, context) if !arg_auth return arg_auth, err else true end else true end end end  | 
  
#ready?(**args) ⇒ Boolean, early_return_data
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).
      124 125 126  | 
    
      # File 'lib/graphql/schema/resolver.rb', line 124 def ready?(**args) true end  | 
  
#resolve(**args) ⇒ Object
Do the work. Everything happens here.
      110 111 112  | 
    
      # File 'lib/graphql/schema/resolver.rb', line 110 def resolve(**args) raise GraphQL::RequiredImplementationMissingError, "#{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.
      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  | 
    
      # File 'lib/graphql/schema/resolver.rb', line 58 def resolve_with_support(**args) # First call the ready? hook which may raise ready_val = if args.any? ready?(**args) else ready? end context.schema.after_lazy(ready_val) do |is_ready, ready_early_return| if ready_early_return if is_ready != false raise "Unexpected result from #ready? (expected `true`, `false` or `[false, {...}]`): [#{.inspect}, #{ready_early_return.inspect}]" else ready_early_return end elsif is_ready # 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 call `authorized?`, which may raise or may return a lazy object = if loaded_args.any? (**loaded_args) else end context.schema.after_lazy() do |(, early_return)| # If the `authorized?` returned two values, `false, early_return`, # then use the early return value instead of continuing if early_return if == false early_return else raise "Unexpected result from #authorized? (expected `true`, `false` or `[false, {...}]`): [#{.inspect}, #{early_return.inspect}]" end elsif # Finally, all the hooks have passed, so resolve it if loaded_args.any? public_send(self.class.resolve_method, **loaded_args) else public_send(self.class.resolve_method) end else nil end end end end end end  |