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
  # Mulitply 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, #metadata, #redefine

Constructor Details

#initializeField



190
191
192
193
194
195
196
197
198
199
# File 'lib/graphql/field.rb', line 190

def initialize
  @complexity = 1
  @arguments = {}
  @resolve_proc = build_default_resolver
  @lazy_resolve_proc = DefaultLazyResolve
  @relay_node_field = false
  @default_arguments = nil
  @connection = false
  @connection_max_page_size = nil
end

Instance Attribute Details

#argumentsHash<String => GraphQL::Argument>



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

def arguments
  @arguments
end

#complexityNumeric, Proc



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

def complexity
  @complexity
end

#connection=(value) ⇒ Object (writeonly)

Sets the attribute connection



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

def connection=(value)
  @connection = value
end

#connection_max_page_sizenil, Integer



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

def connection_max_page_size
  @connection_max_page_size
end

#deprecation_reasonString?



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

def deprecation_reason
  @deprecation_reason
end

#descriptionString?



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

def description
  @description
end

#functionObject, GraphQL::Function



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

def function
  @function
end

#hash_keyObject?



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

def hash_key
  @hash_key
end

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



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

def lazy_resolve_proc
  @lazy_resolve_proc
end

#mutationGraphQL::Relay::Mutation?



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

def mutation
  @mutation
end

#nameString



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

def name
  @name
end

#propertySymbol?



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

def property
  @property
end

#relay_node_fieldBoolean



142
143
144
# File 'lib/graphql/field.rb', line 142

def relay_node_field
  @relay_node_field
end

#relay_nodes_fieldBoolean



145
146
147
# File 'lib/graphql/field.rb', line 145

def relay_nodes_field
  @relay_nodes_field
end

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



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

def resolve_proc
  @resolve_proc
end

Instance Method Details

#connection?Boolean



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

def connection?
  @connection
end

#default_argumentsGraphQL::Query::Arguments



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

def default_arguments
  @default_arguments ||= GraphQL::Query::LiteralInput.defaults_for(self.arguments)
end

#initialize_copy(other) ⇒ Object



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

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

#lazy_resolve(obj, args, ctx) ⇒ Object

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



268
269
270
# File 'lib/graphql/field.rb', line 268

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



273
274
275
# File 'lib/graphql/field.rb', line 273

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.



279
280
281
282
283
# File 'lib/graphql/field.rb', line 279

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)


214
215
216
# File 'lib/graphql/field.rb', line 214

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.



221
222
223
# File 'lib/graphql/field.rb', line 221

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

#to_sObject



258
259
260
# File 'lib/graphql/field.rb', line 258

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

#typeObject

Get the return type for this field.



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

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

#type=(new_return_type) ⇒ Object



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

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