Table of Contents

Fields

This page will explore more advanced features of fields. It would be best if you started from there before reading this content.

Equivalency

All fields and types have an equivalency operator =~. This operator helps to identify if the left side can be used as the right side. The equivalency takes into consideration several different factors, and some specific types of fields have their own extension of this operator. Here are some rules:

  • Both types associated to the fields must be equivalent;
  • Although the right field may have more arguments, all of the left field’s arguments must be present and equivalent to the ones in the right field’s arguments;
  • A not null-able left field is equivalent to a null-able right field.

Event Sources

The events associated to a field may come from several different places. Here is the list of the sources in their proper order of precedence:

  1. Events from directives attached to the field;
  2. Events from directives attached to the type of the field;
  3. Events created using on or shortcuts;

Soon Output fields will be able to have directives added to their arguments, making it another source of events.

Read more about request events.

Metadata

Unavailable This feature is yet to be published.

Metadata is a simple Hash added to fields that may contain any additional information you want to associate with them. See the example below for how to write and read values.

# Writing
field(:name, meta: { counter: 1 })
# OR
field(:name) do
  metadata :counter, 1
end

# Reading
find_field(:name).metadata[:counter]
# OR, on an event
field.metadata[:counter]

Proxies

Field proxies are the most advanced feature of this gem. You can think of it as a selective multi-inheritance. Selective because not all properties are inherited and multi because you can have proxies of proxies.

Proxied fields will have the same class as their source but with a series of Proxied specific extensions. Each type and extension of a field can have its own Proxied module that changes its behavior when working with a proxied field.

Due to proxies, you can define your GraphQL schema in no specific order, and it will still produce consistent APIs. Plus, proxies were designed to work with events, meaning that events from the proxy will be added at the end of the list.

Regular inheritance, sources, importing fields, and implementing interfaces will produce proxies.

Creating

You can create a proxy of a field by adding a new field to any component considered a field list. When you create a proxy, you have a one-time opportunity to give it a different name by passing a second argument or using either :as or :alias named arguments.

proxy_field(GraphQL::User[:name])
# OR
proxy_field(GraphQL::User[:name], as: :user_name)

Identifying

All fields have a proxy? method that will indicate whether it is a proxy. You can also identify that a field is a proxy by checking the result of the inspect of a field, for example:

:001 > GraphQL::AppSchema[:query][:users]
    => #... @source=GraphQL::UserSource[:users] [proxied] ...

Type Resolution

One interesting thing about proxies is that they inherit the type setting, but not the resolved type_klass. This was intentional, to allow proxies to be resolved for more specific types.

For example, if you have two namespaces, you can create a field with a "User" type. Then, when they are imported to their proper schema, each one can be resolved to that schema’s specific User type.

# app/graphql/queries/user.rb
class GraphQL::Queries::User < GraphQL::Query
  returns 'User'
end

# app/graphql/admin_schema.rb
object('User') #        ↰ The type will be this object
add_proxy_field(:query, GraphQL::Queries::User)

# app/graphql/client_schema.rb
interface('User') #     ↰ The type will be this interface
add_proxy_field(:query, GraphQL::Queries::User)

Properties

Here is a list of properties of a proxy field and their respective behavior:

arguments
Concatenated
array
Inherited
authorizer
Changeable
broadcastable
Changeable
description
Changeable
directives
Concatenated
enabled
Changeable
events
Concatenated
full_scope
Concatenated
gql_name
Changeable
listeners
Concatenated
metadata
Concatenated
method_name
Changeable
method_name
Changeable
name
Changeable
null
Inherited
nullable
Inherited
owner
Different
performer
Changeable
resolver
Changeable
type_class
Variable
type
Inherited
  • Changeable: Value is inherited but can be changed in the proxy;
  • Concatenated: Both values are combined to make it one;
  • Different: It will always be different;
  • Inherited: It will always be inherited;
  • Variable: It may vary from the original.

From Interfaces

Proxies created from implementing interfaces have a more restrictive list of things you are allowed to change. In such cases, you cannot rename the field nor change its enabled status.