You are here

How to Build a GraphQL API with Rails in 20 minutes

GraphQL is seen by some as the beginning of the end for RESTful APIs. The Facebook-backed project lets you get all the data you want in the way you want from an API while only ever calling one endpoint. But where to get started? Scott Domes over at MuseFind will take you from zero to hero in only twenty minutes.

You’ll be building a simple API with Rails and GraphQL that will let you see data about people and their pets held in a dedicated database.

Getting Started

First off, simply run the command in the terminal:

rails new people --api
cd people/
rails generate model Person name:string surname:string
rails generate model Pet name:string person:references type:string
rake db:migrate

This will create the API and the database models Person and Pet. You want to populate the db with something so enter ‘rails c’ to enter the Rails command line and then create a couple of models like this:

scott = Person.create(name: 'Scott', surname: 'Domes')
scott.pets.create(name: 'Colby')
scott.pets.create(name: 'Jessie')

Finally, install GraphQL by adding the graphql gem in your Gemfile followed by running ‘bundle install’.

Schemas and Types

In GraphQL, you need to know schemas and types. Schemas define what data is available and what type it is. Types determine the structure of data. Let’s start by creating a type inside types/. Add a file called person_type.rb and add the person type to the file.

PersonType = GraphQL::ObjectType.define do
 name "Person"
  description "A Person"
  field :id, types.ID
  field :name, types.String
  field :surname, types.String
  field :pets do
    type types[PetType]
    resolve -> (person, args, ctx) {

Adding More Types

Along with a person type, we want a PetType. For GraphQL to know where to get the pet data, we need to add a resolve function which takes the pet data from instances of the person type. So add a pet_type file with a resolve function like so:

# types/pet_type.rb
PetType = GraphQL::ObjectType.define do
 name "Pet"
  description "A Pet"
  field :id, types.ID
  field :name, types.String
  field :person do
    type PersonType
    resolve -> (pet, args, ctx) {

Schema and QueryType

To query the data, we need to do three things: define a QueryType, define a schema and make a route to which queries can be directed. For the first, create a new file in types/ folder called query_type.r with the following content.

QueryType = GraphQL::ObjectType.define do
  name "Query"
  description "The query root for this schema"
  field :pets do
    type types[PetType]
    resolve -> (obj, args, ctx) {
  field :people do
    type types[PersonType]
    resolve -> (obj, args, ctx) {

This gives our query two fields ‘:pets’ and ‘:people’. These fields will make sure we can get the right data from the models with Person.all or Pet.all.

To define your schema, simply create a new file in the types/ folder called schema.rb with the content:

Schema = GraphQL::Schema.define do
  query QueryType

Lastly, define your query route by adding the line “post '/query' => 'application#query'” in config/routes.rb. This will allow you to send requests to ‘http://localhost:3001/query’. The requests will be handled by the query method in app controller file at app/controller/application_controller, which we’ll define like so.

# app/controller/application_controller
class ApplicationController < ActionController::API
  def query
    result = Schema.execute(
    render json: result

This code makes sure that when the endpoint is called, we use the GraphQL schema and return a JSON response.

Testing Your Query

You can now test your basic API. To do that, install and open Postman, the API toolchain. Then start up your app server in the command line with ‘rails server -p 3001’. Finally in the Postman interface call the relevant endpoint with the following:

{ "query": "{ pets { name person { name } } }" }

Don’t forget to set the request body to ‘RAW’ in Postman. This request should then return your people and pet data in exactly the way you want it.

Original Article




I would add a step after generating your models.

Add "has_man :pets" inside the Person class, so that the command "scott.pets.create(...)" works.