I just want to leave here my findings for anyone who gets stuck with this in the future and wants to get pointed to a better direction.
First, the graphql-ruby
gem includes everything that is needed to implement a Relay compatible GraphQL API. In includes everything that was before in the graphql-relay
gem.
You need to provide 2 things in your Schema in order to make the Relay refetching feature to work well, an id_from_object
method that converts an object in your domain, into a global id and also a object_from_id
method that will decode the global id into an object in your application:
ApplicationSchema = GraphQL::Schema.define do
/* Create IDs by joining the type name & ID, then base64-encoding it */
id_from_object ->(object, type_definition, query_ctx) {
GraphQL::Schema::UniqueWithinType.encode(type_definition.name, object.id)
}
object_from_id ->(id, query_ctx) {
type_name, object_id = GraphQL::Schema::UniqueWithinType.decode(id)
# Now, based on `type_name` and `id`
# find an object in your application
# This will give the user access to all records in your db
# so you might want to restrict this properly
Object.const_get(type_name).find(object_id)
}
end
Also, all your types should implement the NodeInterface
provided by the ruby gem, and expose a global_id_field
instead of an ID type:
PostType = GraphQL::ObjectType.define do
name "Post"
# Implements the "Node" interface for Relay
interfaces [GraphQL::Relay::Node.interface]
# exposes the global id
global_id_field :id
field :name, types.String
end
This will allow Relay to refetch data like this:
query {
node(id: "RmFjdGlvbjox") {
id
... on Post {
name
}
}
}
Relay also uses a babel-relay-plugin
which requires a schema.json to be generated and available to the client, if you're building an isolated API with no view rendering, the way to go is to let the clients fetch the schema and not to do that work in the server, something like apollo-codegen can work. However, if you are building a rails app and need the schema in the same app, then you can run an instrospection query and save the result to a json file using a rake task:
Schema.execute GraphQL::Introspection::INTROSPECTION_QUERY
Lastly, you'll need to understand that Relay expresses one-to-many relationships with connections:
PostType = GraphQL::ObjectType.define do
# default connection
# obj.comments by default
connection :comments, CommentType.connection_type
# custom connection
connection :featured_comments, CommentType.connection_type do
resolve ->(post, args, ctx) {
comments = post.comments.featured
if args[:since]
comments = comments.where("created_at >= ?", since)
end
comments
}
end
end
Connections support some arguments out of the box, you can use first
, last
, before
and after
in your connection queries:
query {
posts(first: 5) {
edges {
node {
name
}
}
}
}
All of this is documented in the Relay documentation so make sure you read it as well as the graphql-ruby documentation.