A collection of utilities for building GraphQL APIs.
Table of Contents
Add this line to your application's Gemfile:
gem 'graphql-extras'
And then execute:
$ bundle
The graphql
gem will generate a controller for you with a bunch of boilerplate. This module will encapsulate that boilerplate:
class GraphqlController < ApplicationController
include GraphQL::Extras::Controller
def execute
graphql(schema: MySchema, context: { current_user: current_user })
end
end
This allows you to preload associations before resolving fields.
class Schema < GraphQL::Schema
use GraphQL::Dataloader
end
class BaseField < GraphQL::Schema::Field
prepend GraphQL::Extras::Preload
end
class BaseObject < GraphQL::Schema::Object
field_class BaseField
end
class PostType < BaseObject
field :author, AuthorType, preload: :author, null: false
field :author_posts, [PostType], preload: {author: :posts}, null: false
field :depends_on_author, Integer, preload: :author, null: false
def author_posts
object.author.posts
end
end
This is a subclass of GraphQL::Dataloader::Source
that performs eager loading of Active Record associations.
loader = dataloader.with(GraphQL::Extras::PreloadSource, :blog)
loader.load(Post.first)
loader.load_many(Post.all)
In your base classes, you should include the GraphQL::Extras::Types
.
class BaseObject < GraphQL::Schema::Object
include GraphQL::Extras::Types
end
class BaseInputObject < GraphQL::Schema::InputObject
include GraphQL::Extras::Types
end
This scalar takes a Date
and transmits it as a string, using ISO 8601 format.
field :birthday, Date, required: true
This scalar takes a DateTime
and transmits it as a string, using ISO 8601 format.
field :created_at, DateTime, required: true
Note: This is just an alias for the ISO8601DateTime
type that is included in the graphql
gem.
This scalar takes a BigDecimal
and transmits it as a string.
field :weight, BigDecimal, required: true
This scalar is used for accepting file uploads.
field :image, Upload, required: true
It achieves this by passing in all file upload parameters through context. This will work out of the box if you're using GraphQL::Extras::Controller
.
Here's an example using CURL:
$ curl -X POST \
-F query='mutation { uploadFile(image: "image") }' \
-F image=@cats.png \
localhost:3000/graphql
Take note of the correspondence between the value "image"
and the additional HTTP parameter called -F image=@cats.png
.
See apollo-link-upload for the client-side implementation.
This module makes it really easy to test your schema.
First, create a test schema:
# spec/support/test_schema.rb
require "graphql/extras/test"
class TestSchema < GraphQL::Extras::Test::Schema
configure schema: Schema, queries: "spec/**/*.graphql"
end
Now, you can run tests like so:
require "support/test_schema"
RSpec.describe "hello" do
let(:context) { { name: "Ray" } }
let(:schema) { TestSchema.new(context) }
it "allows easily executing queries" do
query = schema.hello
expect(query).to be_successful
expect(query.data["hello"]).to eq("world")
end
it "parses errors" do
query = schema.kaboom
expect(query).not_to be_successful
expect(query.errors[0].message).to eq("Invalid")
expect(query.errors[0].code).to eq("VALIDATION_ERROR")
end
end
To install dependencies:
$ bundle install
To run the test suite:
$ bundle exec rspec
Bug reports and pull requests are welcome on GitHub at https://github.com/rzane/graphql-extras.
GraphQL::Extras is released under the MIT License.