Table of Contents

Field Lists

Field lists are found in classes that contain a single list of fields (Interfaces, Inputs, Objects, and Sets) or multi-schema-based fields (Schemas and Sources).

You can pretty much call the same methods in both scenarios, and the difference is that you need to provide the type in the multi-schema-based ones. However, when using the block to focus on one specific schema type, you can treat the block as if you were dealing with a single list of fields.

# Single list of fields
disable_fields(:field1, :field2)

# Multi-schema-based list of fields
disable_fields(:query, :field1, :field2)

# Using the block to interact with the multi-schema-based list of fields
query_fields do
  disable_fields(:field1, :field2)
end

When the name is different between single and multi, they will be listed as single / multi.

The List

Accessing

fields(initialize = nil) /
fields_for(type, initialize = nil)

Returns the list of fields. They all use Concurrent::Map with the sanitized name as the keys and the fields as the values. The list is only initialized when explicitly requested, otherwise, it will return nil.

# Single form
fields                       # May return nil
fields(true)                 # Always returns a Concurrent::Map

# Multi form
fields_for(:query)           # May return nil
fields_for(:query, true)     # Always returns a Concurrent::Map

Checking

fields? /
fields_for?(type)

Check if the list of fields has been initialized and has items.

# Single form
fields?

# Multi form
fields_for?(:query)

Adding Fields

Regular

field(name, type, **settings, &configure_block) /
add_field(type, name, type, **settings, &configure_block)

Allows you to add a field to the list. Fields within a list needs to have a unique name. If a field with the same name already exists, a DuplicatedError will be raised.

# Single form
field(:name, :string)

# Multi form
add_field(:query, :name, :string)

Read more about fields.

Safe

safe_field(name, type, **settings, &configure_block) /
safe_add_field(type, name, type, **settings, &configure_block)

This works similarly to the above version, except that the exception is already rescued for you. It’s best used with Sources.

# Single form
safe_field(:name, :string)

# Multi form
safe_add_field(:query, :name, :string)

Proxy

proxy_field(field, alias = nil, **settings, &configure_block) /
add_proxy_field(type, field, alias = nil, **settings, &configure_block)

Add a field that is a proxy to the other provided field. This not only checks for the uniqueness of the name but also if the provided one is compatible with the list, you can’t add a proxy to a mutation field on a query list, for example.

# Single form
proxy_field(GraphQL::User[:name])

# You can give it a different name when adding the proxy
proxy_field(GraphQL::User[:name], :user_name)
# OR
proxy_field(GraphQL::User[:name], as: :user_name)
# OR
proxy_field(GraphQL::User[:name], alias: :user_name)

# Multi form
add_proxy_field(:query, GraphQL::User[:name])

Proxy fields is an advanced feature. Read more about proxy fields.

Importing

From Class

import(source) /
import_into(type, source)

Allows importing one or multiple fields from the given source into the list. Importing means that all fields will be added as proxies of the source’s fields. The source can be an Array, a Hash-like with the fields on the values, another object with a list of fields, a Set Alternative, or a Standalone Alternative.

# Single form
import(GraphQL::WithName)

# Multi form
import_into(:query, GraphQL::Queries::Users)

From Module

import_all(module, recursive: false) /
import_all_into(type, module, recursive: false)

Allows importing several classes of fields from the given module into the list. This is a powerful feature for organizing and sharing your code. For every constant found in the module, call the above method if the constant is a class or call itself again if running recursively and the constant is another module.

# Single form
import_all(GraphQL::UserFields)

# Multi form
import_all_into(:query, GraphQL::Queries)

NO EQUIVALENCY /
import_all(module, recursive: false)

The multi-schema-based list has a syntax sugar for importing a whole module where its name already dictates what type is being imported.

# Multi form
import_all(GraphQL::Queries)

Changing Fields

Simple

change_field(name, **changes, &configure_block) or
overwrite_field(name, **changes, &configure_block)

You can use this to change several aspects of your your fields, which supports a block to change even more aspects.

# Single form
change_field(:name, null: true)

# With a block
change_field(:name, null: true) do
  argument(:first, :bool, null: false, default: true)
end

# Using the alias
overwrite_field(:name, null: true)

# Multi form
change_field(:query, :name, null: true)

Block Only

configure_field(name, &configure_block)

This is a subset of the above, where the objective is to go straightforward to the block. Use this method when the changes only involve adding arguments or directives.

# Single form
configure_field(:name) do
  argument(:first, :bool, null: false, default: true)
end

# Multi form
configure_field(:query, :name) do
  argument(:first, :bool, null: false, default: true)
end

Disable Fields

disable_fields(name, *names)

A quick shortcut to change the enabled status of one or more fields to false.

# Single form
disable_fields(:field1, :field2)

# Multi form
disable_fields(:query, :field1, :field2)

Enable Fields

enable_fields(name, *names)

A quick shortcut to change the enabled status of one or more fields to true.

# Single form
enable_fields(:field1, :field2)

# Multi form
enable_fields(:query, :field1, :field2)

Read more about changing fields.

Searching Fields

Checking

has_field?(by)

Checks if the list has a field. It accepts the name as a symbol, the GQL name as a string, or another field, as in checking a field with the same name.

# Single form
has_field?(:first_name)
has_field?('firstName')

# Multi form
has_field?(:query, :first_name)
has_field?(:query, 'firstName')

Finding

find_field(by) or [by]

Look for a field and return it. It accepts the name as a symbol, the GQL name as a string, or another field, as in finding a field with the same name.

# Single form
find_field(:first_name)
find_field('firstName')

# OR
self[:first_name]
self['firstName']

# Multi form
find_field(:query, :first_name)
find_field(:query, 'firstName')

# OR
self[:query, :first_name]
self[:query, 'firstName']

Force Finding

find_field!(by)

Same as above, but it will raise a NotFoundError if the field was not found.

# Single form
find_field!(:first_name)
find_field!('firstName')

# Multi form
find_field!(:query, :first_name)
find_field!(:query, 'firstName')

Others

All Field Names

field_names(enabled_only = true) /
field_names_for(type, enabled_only = true)

Get a list of all the GQL names of the fields in the list. By default, it returns only enabled fields. Passing a second argument as false will return from all fields.

# Single form
field_names                       # => ['fieldOne']
field_names(false)                # => ['fieldOne', 'disabledFieldTwo']

# Multi form
field_names_for(:query)           # => ['fieldOne']
field_names_for(:query, false)    # => ['fieldOne', 'disabledFieldTwo']

Read more about names.

Enabled Fields

enabled_fields /
enabled_fields_from(type)

Returns an iterable list of all the enabled fields. It uses an Enumerator::Lazy for performance purposes.

# Single form
enabled_fields.each { |field| puts field.gql_name }

# Multi form
enabled_fields_from(:query).each { |field| puts field.gql_name }

Attaching Directives

Unavailable This feature is yet to be published.

attach(directive, to: , **arguments) /
attach(directive, to: , fields: , **arguments)

Allows attaching a directive, by instance or name plus arguments, to one or more fields.

# Single form
attach(GraphQL::DeprecatedDirective(), to: %i[users user])

# Multi form
attach(GraphQL::DeprecatedDirective(), to: :query, fields: %i[users user])

# Using name and arguments
attach(:deprecated, reason: 'Just because.', to: %i[users user])

Multi form Only

The multi-schema-based list provides a series of methods per type as syntax sugar to interact with their specific list.

Accessing

{type}_fields

Access the list of fields of that type. It supports a block to interact exclusively with that list. Different from the regular access, this alone will never initialize the list.

# Accessing
query_fields
mutation_fields
subscription_fields

# Interacting
query_fields {  }
mutation_fields {  }
subscription_fields {  }

Checking

{type}_fields?

Check if the list of that type has been initialized and has items.

query_fields?
mutation_fields?
subscription_fields?

Adding Fields

add_{type}_field(name, type, **settings, &configure_block)

Works as a shortcut for the regular form of adding fields.

add_query_field(:name, :string)
add_mutation_field(:name, :string)
add_subscription_field(:name, :string)

Checking for a Field

{type}_field?(by)

Works as a shortcut for the has_field?.

query_field?(:name)
mutation_field?(:name)
subscription_field?(:name)

Finding a Field

{type}_field(by)

Works as a shortcut for the find_field.

query_field(:name)
mutation_field(:name)
subscription_field(:name)

The Type Name

{type}_type_name

Returns the name of the Type of the list as it is exposed to GraphQL schema.

query_type_name            # _Query
mutation_type_name         # _Mutation
subscription_type_name     # _Subscription

Type Object

{type}_type

It returns an OpenStruct that acts like a fake Object for that type. The fake type is only returned if there are fields added to that list.

# app/graphql/app_schema.rb
query_type

# Returns
OpenStruct.new(
  name: "GraphQL::AppSchema[:query]",
  kind: :object,
  object?: true,
  kind_enum: 'OBJECT',
  fields: @query_fields,
  gql_name: '_Query',
  description: nil,
  interfaces?: false,
  internal?: false,
).freeze