Class: GraphQL::Field

Inherits:
Object
  • Object
show all
Includes:
Define::InstanceDefinable
Defined in:
lib/graphql/field.rb,
lib/graphql/field/resolve.rb

Overview

Fields belong to ObjectTypes and InterfaceTypes.

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.

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 { … }`.

## 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.

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]`

## Arguments

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

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

Only certain types maybe used for inputs:

  • Scalars

  • Enums

  • Input Objects

  • Lists of those types

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.

Examples:

Lazy type resolution

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

Defining a field with a block

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

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

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

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

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

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

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

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

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

Defined Under Namespace

Modules: DefaultLazyResolve, Resolve

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Define::InstanceDefinable

#define, included, #metadata, #redefine

Constructor Details

#initializeField

Returns a new instance of Field.


213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/graphql/field.rb', line 213

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

Instance Attribute Details

#argumentsHash<String => GraphQL::Argument>

Returns Map String argument names to their Argument implementations.

Returns:


168
169
170
# File 'lib/graphql/field.rb', line 168

def arguments
  @arguments
end

#arguments_classObject

Returns the value of attribute arguments_class


185
186
187
# File 'lib/graphql/field.rb', line 185

def arguments_class
  @arguments_class
end

#complexityNumeric, Proc

Returns The complexity for this field (default: 1), as a constant or a proc like `->(query_ctx, args, child_complexity) { } # Numeric`.

Returns:

  • (Numeric, Proc)

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


174
175
176
# File 'lib/graphql/field.rb', line 174

def complexity
  @complexity
end

#connection=(value) ⇒ Object (writeonly)

Sets the attribute connection

Parameters:

  • value

    the value to set the attribute connection to.


187
188
189
# File 'lib/graphql/field.rb', line 187

def connection=(value)
  @connection = value
end

#connection_max_page_sizenil, Integer

Returns:

  • (nil, Integer)

211
212
213
# File 'lib/graphql/field.rb', line 211

def connection_max_page_size
  @connection_max_page_size
end

#deprecation_reasonString?

Returns The client-facing reason why this field is deprecated (if present, the field is deprecated).

Returns:

  • (String, nil)

    The client-facing reason why this field is deprecated (if present, the field is deprecated)


165
166
167
# File 'lib/graphql/field.rb', line 165

def deprecation_reason
  @deprecation_reason
end

#descriptionString?

Returns The client-facing description of this field.

Returns:

  • (String, nil)

    The client-facing description of this field


162
163
164
# File 'lib/graphql/field.rb', line 162

def description
  @description
end

#edge_classnil, 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.

Returns:

  • (nil, Class)

203
204
205
# File 'lib/graphql/field.rb', line 203

def edge_class
  @edge_class
end

#functionObject, GraphQL::Function

Returns The function used to derive this field.

Returns:


183
184
185
# File 'lib/graphql/field.rb', line 183

def function
  @function
end

#hash_keyObject?

Returns The key to access with `obj.[]` to resolve this field (overrides #name if present).

Returns:

  • (Object, nil)

    The key to access with `obj.[]` to resolve this field (overrides #name if present)


180
181
182
# File 'lib/graphql/field.rb', line 180

def hash_key
  @hash_key
end

#introspection=(value) ⇒ Object (writeonly)

Sets the attribute introspection

Parameters:

  • value

    the value to set the attribute introspection to.


188
189
190
# File 'lib/graphql/field.rb', line 188

def introspection=(value)
  @introspection = value
end

#lazy_resolve_proc<#call(obj, args, ctx)> (readonly)

Returns A proc-like object which can be called trigger a lazy resolution.

Returns:

  • (<#call(obj, args, ctx)>)

    A proc-like object which can be called trigger a lazy resolution


156
157
158
# File 'lib/graphql/field.rb', line 156

def lazy_resolve_proc
  @lazy_resolve_proc
end

#mutationGraphQL::Relay::Mutation?

Returns The mutation this field was derived from, if it was derived from a mutation.

Returns:


171
172
173
# File 'lib/graphql/field.rb', line 171

def mutation
  @mutation
end

#nameString

Returns The name of this field on its ObjectType (or InterfaceType).

Returns:


159
160
161
# File 'lib/graphql/field.rb', line 159

def name
  @name
end

#propertySymbol?

Returns The method to call on `obj` to return this field (overrides #name if present).

Returns:

  • (Symbol, nil)

    The method to call on `obj` to return this field (overrides #name if present)


177
178
179
# File 'lib/graphql/field.rb', line 177

def property
  @property
end

#relay_node_fieldBoolean

Returns True if this is the Relay find-by-id field.

Returns:

  • (Boolean)

    True if this is the Relay find-by-id field


147
148
149
# File 'lib/graphql/field.rb', line 147

def relay_node_field
  @relay_node_field
end

#relay_nodes_fieldBoolean

Returns True if this is the Relay find-by-ids field.

Returns:

  • (Boolean)

    True if this is the Relay find-by-ids field


150
151
152
# File 'lib/graphql/field.rb', line 150

def relay_nodes_field
  @relay_nodes_field
end

#resolve_proc<#call(obj, args, ctx)> (readonly)

Returns A proc-like object which can be called to return the field's value.

Returns:

  • (<#call(obj, args, ctx)>)

    A proc-like object which can be called to return the field's value


153
154
155
# File 'lib/graphql/field.rb', line 153

def resolve_proc
  @resolve_proc
end

#subscription_scopenil, String

Returns Prefix for subscription names from this field.

Returns:

  • (nil, String)

    Prefix for subscription names from this field


191
192
193
# File 'lib/graphql/field.rb', line 191

def subscription_scope
  @subscription_scope
end

#traceBoolean

Returns True if this field should be traced. By default, fields are only traced if they are not a ScalarType or EnumType.

Returns:

  • (Boolean)

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


194
195
196
# File 'lib/graphql/field.rb', line 194

def trace
  @trace
end

Instance Method Details

#connection?Boolean

Returns:

  • (Boolean)

197
198
199
# File 'lib/graphql/field.rb', line 197

def connection?
  @connection
end

#edges?Boolean

Returns:

  • (Boolean)

206
207
208
# File 'lib/graphql/field.rb', line 206

def edges?
  !!@edge_class
end

#initialize_copy(other) ⇒ Object


226
227
228
229
# File 'lib/graphql/field.rb', line 226

def initialize_copy(other)
  super
  @arguments = other.arguments.dup
end

#introspection?Boolean

Returns Is this field a predefined introspection field?.

Returns:

  • (Boolean)

    Is this field a predefined introspection field?


232
233
234
# File 'lib/graphql/field.rb', line 232

def introspection?
  @introspection
end

#lazy_resolve(obj, args, ctx) ⇒ Object

If #resolve returned an object which should be handled lazily, this method will be called later to force the object to return its value.

Parameters:

Returns:

  • (Object)

    The result of calling the registered method on `obj`


297
298
299
# File 'lib/graphql/field.rb', line 297

def lazy_resolve(obj, args, ctx)
  @lazy_resolve_proc.call(obj, args, ctx)
end

#lazy_resolve=(new_lazy_resolve_proc) ⇒ Object

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


302
303
304
# File 'lib/graphql/field.rb', line 302

def lazy_resolve=(new_lazy_resolve_proc)
  @lazy_resolve_proc = new_lazy_resolve_proc
end

#prepare_lazy(obj, args, ctx) ⇒ GraphQL::Execution::Lazy

Prepare a lazy value for this field. It may be `then`-ed and resolved later.

Returns:


308
309
310
311
312
# File 'lib/graphql/field.rb', line 308

def prepare_lazy(obj, args, ctx)
  GraphQL::Execution::Lazy.new {
    lazy_resolve(obj, args, ctx)
  }
end

#resolve(object, arguments, context) ⇒ Object

Get a value for this field

Examples:

resolving a field value

field.resolve(obj, args, ctx)

Parameters:

  • object (Object)

    The object this field belongs to

  • arguments (Hash)

    Arguments declared in the query

  • context (GraphQL::Query::Context)

243
244
245
# File 'lib/graphql/field.rb', line 243

def resolve(object, arguments, context)
  resolve_proc.call(object, arguments, context)
end

#resolve=(new_resolve_proc) ⇒ Object

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.

Parameters:

  • new_resolve_proc (<#call(obj, args, ctx)>, nil)

250
251
252
# File 'lib/graphql/field.rb', line 250

def resolve=(new_resolve_proc)
  @resolve_proc = new_resolve_proc || build_default_resolver
end

#to_sObject


287
288
289
# File 'lib/graphql/field.rb', line 287

def to_s
  "<Field name:#{name || "not-named"} desc:#{description} resolve:#{resolve_proc}>"
end

#typeObject

Get the return type for this field.


260
261
262
# File 'lib/graphql/field.rb', line 260

def type
  @clean_type ||= GraphQL::BaseType.resolve_related_type(@dirty_type)
end

#type=(new_return_type) ⇒ Object


254
255
256
257
# File 'lib/graphql/field.rb', line 254

def type=(new_return_type)
  @clean_type = nil
  @dirty_type = new_return_type
end