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