GraphQL + Rails


GraphQL is a another way to build your APIs.

First of all - I would say what GraphQL is not a REST “killer” or replacement for REST, it’s a completely different concept.

You can find a tons of “comparison” between REST and GrahpQL, and topics about “why” and “when” you should use it.

Let’s see some quick checkpoints:

  • REST and GraphQL are totally different
  • GraphQL isn’t a magic bullet, nor is it “better”
  • You can use both at the same time
  • GraphQL is great tools if used for the right thing

So, let’s start. As a example project, I’ll use my small pet project for our office purposes runboard.

Simple add graphql into your Gemfile.

gem 'graphql'

And run installer script. It creates some GraphQL specific files in your project.

rails generate graphql:install

routes.rb

post '/graphql', to: 'graphql#query'

So, we are ready to write our first queries.

All root queries we should describe in QueryType Type, for example like this:

#/app/graphql/types/query_type.rb

Types::QueryType = GraphQL::ObjectType.define do
  name "Query"
  field :users, !types[Types::UserType] do
    argument :limit, types.Int, default_value: 10, prepare: -> (limit) { [limit, 30].min }
    resolve -> (obj, args, ctx) {
      User.limit(args[:limit]).order(id: :desc)
    }
  end

  field :projects, !types[Types::ProjectType] do
    argument :limit, types.Int, default_value: 10, prepare: -> (limit) { [limit, 30].min }
    resolve -> (obj, args, ctx) {
      Project.limit(args[:limit]).order(id: :desc)
    }
  end
end

Nothing unclear here, right? Simple ActiveRecord queries in field blocks.

After that, we need to create our first Type for our User and Project models:

#/app/graphql/types/user_type.rb

Types::UserType = GraphQL::ObjectType.define do
  name 'User'

  field :id, !types.ID
  field :login, !types.String
  field :bio, types.String
  field :avatar, types.String
  field :phone, types.String
  field :position, types.String
  field :name, types.String
  field :email, types.String

  field :projects, !types[Types::ProjectType] do
    argument :limit, types.Int, default_value: 10, prepare: -> (limit) { [limit, 30].min }
    resolve -> (obj, args, ctx) {
      obj.projects.limit(args[:limit])
    }
  end

  field :updated_at do
    type types.Int

    resolve -> (obj, args, ctx) {
      obj.updated_at.to_i
    }
  end

  field :created_at do
    type types.Int

    resolve -> (obj, args, ctx) {
      obj.created_at.to_i
    }
  end
end
#/app/graphql/types/query_type.rb

Types::ProjectType = GraphQL::ObjectType.define do
  name 'Project'

  field :id, !types.ID
  field :title, !types.String
  field :description, !types.String
  field :logo, !types.String
end

After that, we are ready for our queries!

P.S You can use web graphiql or desktop version.

GrahpQL