Table of Contents
Unions
union User | Admin
Unions allow you to group different objects into one single type. You can think of unions as a sort of composition. They work great with Spreads. Unlike interfaces, unions can’t have fields.
Creating a Union
You can define unions on a file or using the shortcut on the schema.
# app/graphql/unions/person.rb
module GraphQL
class Person < GraphQL::Union
# This is a union of User and Admin object types
append User, Admin
end
end
# OR
# app/graphql/app_schema.rb
union 'Person' do
append User, Admin
end
# OR even
union 'Person', of_types: %w[User Admin]
The last one is preferable because, for now, the only thing you can do with unions besides appending the types is using directives. Plus, it follows the rule of not referencing types by their actual classes.
Read more about recommendations.
Description
Allows documenting unions. This value can be retrieved using introspection
or during a to_gql output. Within the class, desc
works as a syntax sugar for self.description = ''
. It also supports descriptions from
I18n.
# app/graphql/unions/person.rb
module GraphQL
class Person < GraphQL::Union
desc 'This is awesome!'
end
end
Type Resolution
Unions have a special type_for(value, request)
class-level method, which is
responsible for finding an object for the given value
.
The default behavior is to go over the list of members in reverse and find the
first one that is a valid_member?
of value
.
If for some reason, that is not compatible with your application, you can override this method. For example, this relies on ActiveRecord single table inheritance column.
# app/graphql/unions/person.rb
def self.type_for(value, request)
request.find_type(value.type)
end
Important It’s recommended to use
request.find_type
with either the symbol or string name because the resolution is cached during the request and complies with namespaces.
Such translation is possible because object names match type names when using sources. An even more accurate version would be
value.type.tr(':', '')
.
For gem Creators
Once you have created your unions in your gem, remember to add them into
config.known_dependencies
.
It is not recommended to require
such files in your gem.
Rails::GraphQL.config.known_dependencies[:union].update(
my_gem_union: "#{__dir__}/unions/my_gem_union",
)
Using Unions
Once they are defined, you can set them as the type of output fields. Then, in your execution document, you can use spreads to properly capture unique information of the respective types.
Since unions do not contain a list of fields, you can never request fields directly from them besides
__typename
.
field(:recipient, 'Person')
{
recipient {
# Gets the name of the type
__typename
... on User {
# Email is a common attribute, but unions don't hold fields
email
# Slug is a field only available on User
slug
}
... on Admin {
# Email is a common attribute, but unions don't hold fields
email
# Role is a field only available on Admin
role
}
}
}
Unions is the best place for you to set up your
belongs_to
Polymorphic Associations.