class GraphQL::Field

{Field}s belong to {ObjectType}s and {InterfaceType}s.

They're usually created with the `field` helper. If you create it by hand, make sure {#name} is a String.

A field must have a return type, but if you want to defer the return type calculation until later, you can pass a proc for the return type. That proc will be called when the schema is defined.

@example Lazy type resolution

# If the field's type isn't defined yet, you can pass a proc
field :city, -> { TypeForModelName.find("City") }

For complex field definition, you can pass a block to the `field` helper, eg `field :name do … end`. This block is equivalent to calling `GraphQL::Field.define { … }`.

@example Defining a field with a block

field :city, CityType do
  # field definition continues inside the block
end

## Resolve

Fields have `resolve` functions to determine their values at query-time. The default implementation is to call a method on the object based on the field name.

@example Create a field which calls a method with the same name.

GraphQL::ObjectType.define do
  field :name, types.String, "The name of this thing "
end

You can specify a custom proc with the `resolve` helper.

There are some shortcuts for common `resolve` implementations:

- Provide `property:` to call a method with a different name than the field name
- Provide `hash_key:` to resolve the field by doing a key lookup, eg `obj[:my_hash_key]`

@example Create a field that calls a different method on the object

GraphQL::ObjectType.define do
  # use the `property` keyword:
  field :firstName, types.String, property: :first_name
end

@example Create a field looks up with `[hash_key]`

GraphQL::ObjectType.define do
  # use the `hash_key` keyword:
  field :firstName, types.String, hash_key: :first_name
end

## Arguments

Fields can take inputs; they're called arguments. You can define them with the `argument` helper.

@example Create a field with an argument

field :students, types[StudentType] do
  argument :grade, types.Int
  resolve ->(obj, args, ctx) {
    Student.where(grade: args[:grade])
  }
end

They can have default values which will be provided to `resolve` if the query doesn't include a value.

@example Argument with a default value

field :events, types[EventType] do
  # by default, don't include past events
  argument :includePast, types.Boolean, default_value: false
  resolve ->(obj, args, ctx) {
    args[:includePast] # => false if no value was provided in the query
    # ...
  }
end

Only certain types maybe used for inputs:

Input types may also be non-null – in that case, the query will fail if the input is not present.

## Complexity

Fields can have complexity values which describe the computation cost of resolving the field. You can provide the complexity as a constant with `complexity:` or as a proc, with the `complexity` helper.

@example Custom complexity values

# Complexity can be a number or a proc.

# Complexity can be defined with a keyword:
field :expensive_calculation, !types.Int, complexity: 10

# Or inside the block:
field :expensive_calculation_2, !types.Int do
  complexity ->(ctx, args, child_complexity) { ctx[:current_user].staff? ? 0 : 10 }
end

@example Calculating the complexity of a list field

field :items, types[ItemType] do
  argument :limit, !types.Int
  # Multiply the child complexity by the possible items on the list
  complexity ->(ctx, args, child_complexity) { child_complexity * args[:limit] }
end

@example Creating a field, then assigning it to a type

name_field = GraphQL::Field.define do
  name("Name")
  type(!types.String)
  description("The name of this thing")
  resolve ->(object, arguments, context) { object.name }
end

NamedType = GraphQL::ObjectType.define do
  # The second argument may be a GraphQL::Field
  field :name, name_field
end

Attributes

arguments[RW]

@return [Hash<String => GraphQL::Argument>] Map String argument names to their {GraphQL::Argument} implementations

arguments_class[RW]
ast_node[RW]
complexity[RW]

@return [Numeric, Proc] The complexity for this field (default: 1), as a constant or a proc like `->(query_ctx, args, child_complexity) { } # Numeric`

connection[W]
connection_max_page_size[RW]

@return [nil, Integer]

deprecation_reason[RW]

@return [String, nil] The client-facing reason why this field is deprecated (if present, the field is deprecated)

description[RW]

@return [String, nil] The client-facing description of this field

edge_class[RW]

@return [nil, Class] @api private

function[RW]

@return [Object, GraphQL::Function] The function used to derive this field

graphql_name[RW]

@return [String] The name of this field on its {GraphQL::ObjectType} (or {GraphQL::InterfaceType})

hash_key[RW]

@return [Object, nil] The key to access with `obj.[]` to resolve this field (overrides {#name} if present)

introspection[W]
lazy_resolve_proc[R]

@return [<#call(obj, args, ctx)>] A proc-like object which can be called trigger a lazy resolution

mutation[RW]

@return [GraphQL::Relay::Mutation, nil] The mutation this field was derived from, if it was derived from a mutation

name[RW]

@return [String] The name of this field on its {GraphQL::ObjectType} (or {GraphQL::InterfaceType})

property[RW]

@return [Symbol, nil] The method to call on `obj` to return this field (overrides {#name} if present)

relay_node_field[RW]

@return [Boolean] True if this is the Relay find-by-id field

relay_nodes_field[RW]

@return [Boolean] True if this is the Relay find-by-ids field

resolve_proc[R]

@return [<#call(obj, args, ctx)>] A proc-like object which can be called to return the field's value

subscription_scope[RW]

@return [nil, String] Prefix for subscription names from this field

trace[RW]

@return [Boolean] True if this field should be traced. By default, fields are only traced if they are not a ScalarType or EnumType.

Public Class Methods

new() click to toggle source
# File lib/graphql/field.rb, line 215
def initialize
  @complexity = 1
  @arguments = {}
  @resolve_proc = build_default_resolver
  @lazy_resolve_proc = DefaultLazyResolve
  @relay_node_field = false
  @connection = false
  @connection_max_page_size = nil
  @edge_class = nil
  @trace = nil
  @introspection = false
end

Public Instance Methods

connection?() click to toggle source

@return [Boolean]

# File lib/graphql/field.rb, line 199
def connection?
  @connection
end
edges?() click to toggle source

@return [Boolean]

# File lib/graphql/field.rb, line 208
def edges?
  !!@edge_class
end
hash_key=(new_hash_key) click to toggle source

@param new_hash_key [Symbol] A key to access with `#[key]` to resolve this field. Overrides the existing resolve proc.

# File lib/graphql/field.rb, line 285
def hash_key=(new_hash_key)
  @hash_key = new_hash_key
  self.resolve = nil # reset resolve proc
end
initialize_copy(other) click to toggle source
# File lib/graphql/field.rb, line 228
def initialize_copy(other)
  ensure_defined
  super
  @arguments = other.arguments.dup
end
introspection?() click to toggle source

@return [Boolean] Is this field a predefined introspection field?

# File lib/graphql/field.rb, line 235
def introspection?
  @introspection
end
lazy_resolve(obj, args, ctx) click to toggle source

If {#resolve} returned an object which should be handled lazily, this method will be called later to force the object to return its value. @param obj [Object] The {#resolve}-provided object, registered with {Schema#lazy_resolve} @param args [GraphQL::Query::Arguments] Arguments to this field @param ctx [GraphQL::Query::Context] Context for this field @return [Object] The result of calling the registered method on `obj`

# File lib/graphql/field.rb, line 300
def lazy_resolve(obj, args, ctx)
  @lazy_resolve_proc.call(obj, args, ctx)
end
lazy_resolve=(new_lazy_resolve_proc) click to toggle source

Assign a new resolve proc to this field. Used for {#lazy_resolve}

# File lib/graphql/field.rb, line 305
def lazy_resolve=(new_lazy_resolve_proc)
  @lazy_resolve_proc = new_lazy_resolve_proc
end
name=(new_name) click to toggle source
# File lib/graphql/field.rb, line 267
def name=(new_name)
  old_name = @name
  @name = new_name

  if old_name != new_name && @resolve_proc.is_a?(Field::Resolve::NameResolve)
    # Since the NameResolve would use the old field name,
    # reset resolve proc when the name has changed
    self.resolve = nil
  end
end
prepare_lazy(obj, args, ctx) click to toggle source

Prepare a lazy value for this field. It may be `then`-ed and resolved later. @return [GraphQL::Execution::Lazy] A lazy wrapper around `obj` and its registered method name

# File lib/graphql/field.rb, line 311
def prepare_lazy(obj, args, ctx)
  GraphQL::Execution::Lazy.new {
    lazy_resolve(obj, args, ctx)
  }
end
property=(new_property) click to toggle source

@param new_property [Symbol] A method to call to resolve this field. Overrides the existing resolve proc.

# File lib/graphql/field.rb, line 279
def property=(new_property)
  @property = new_property
  self.resolve = nil # reset resolve proc
end
resolve(object, arguments, context) click to toggle source

Get a value for this field @example resolving a field value

field.resolve(obj, args, ctx)

@param object [Object] The object this field belongs to @param arguments [Hash] Arguments declared in the query @param context [GraphQL::Query::Context]

# File lib/graphql/field.rb, line 246
def resolve(object, arguments, context)
  resolve_proc.call(object, arguments, context)
end
resolve=(new_resolve_proc) click to toggle source

Provide a new callable for this field's resolve function. If `nil`, a new resolve proc will be build based on its {#name}, {#property} or {#hash_key}. @param new_resolve_proc [<#call(obj, args, ctx)>, nil]

# File lib/graphql/field.rb, line 253
def resolve=(new_resolve_proc)
  @resolve_proc = new_resolve_proc || build_default_resolver
end
to_s() click to toggle source
# File lib/graphql/field.rb, line 290
def to_s
  "<Field name:#{name || "not-named"} desc:#{description} resolve:#{resolve_proc}>"
end
type() click to toggle source

Get the return type for this field.

# File lib/graphql/field.rb, line 263
def type
  @clean_type ||= GraphQL::BaseType.resolve_related_type(@dirty_type)
end
type=(new_return_type) click to toggle source
# File lib/graphql/field.rb, line 257
def type=(new_return_type)
  @clean_type = nil
  @dirty_type = new_return_type
end

Private Instance Methods

build_default_resolver() click to toggle source
# File lib/graphql/field.rb, line 319
def build_default_resolver
  GraphQL::Field::Resolve.create_proc(self)
end