Rails Kitchen

It's a place to write on stuff I learned recently.

A GraphQL Server Implementation - Ruby on Rails

| Comments

GraphQL is a query language for APIs developed by the Facebook team. This language gives clients the power to ask for exactly what they need and nothing more makes it easier to evolve APIs over time and enables powerful developer tools. Facebook open sourced it in 2015.

video courtesy: graphql.org

A GraphQL request can be either a query (read operation) or a mutation (write operation). For both cases, the request is a simple string that a GraphQL service can interpret, execute, and resolve with data in a specified format.

Main features of GraphQL are:

Retrieve only the data your client needs in a single request - No over-fetching:

Send a GraphQL query to your API with the fields you want to fetch and get only that set of fields in return. Apps using GraphQL are fast and stable because they control the data they get, not the server.

Get many resources in a single round-trip:

We can create queries with a different combination of datasets which will avoid multiple requests to fetch required data, thereby eliminating overheads.

Describe what’s possible with a type system:

GraphQL APIs have a single endpoint and it organizes API with requesting types and fields.

Evolve your API without versions - maintainability:

Add new fields and types to your GraphQL API without impacting existing queries. Aging fields can be deprecated and hidden from tools. By using a single evolving version, GraphQL APIs give apps continuous access to new features and encourage cleaner, more maintainable server code.

GraphQL Queries:

Here’s an example of a GraphQL query that a client can use to ask a server about the name and email of user #1:

1
2
3
4
5
6
7
{
  user(id: 1) {
    firstName,
    lastName,
    email
  }
}
Here’s a possible JSON response for that query:
1
2
3
4
5
6
7
8
9
{
  "data": {
    "user": {
      "firstName": "Shaiju",
      "lastName": "E",
      "email": "eshaiju@gmail.com"
     }
   }
}
GraphQL server implementation in Ruby On Rails Application

Here we are assuming, we have an existing ROR application with model Article and fields title and body.

You can install graphql from RubyGems by adding to your application’s Gemfile:
Gemfile
1
2
3
# Gemfile
gem "graphql"
gem 'graphiql-rails', group: :development
Then, run bundle install.

Now you can get started with a few GraphQL generators:
1
rails g graphql:install
This will:
  • Set up a folder structure in app/graphql/
  • Add schema definition
  • Add a query type definition
  • Add a route and controller for executing queries
  • After installing you can see your new schema by:
    1
    2
    3
    
    bundle install
    rails server
    open localhost:3000/graphiql
    After this, you can build a GraphQL server by hand or GraphQL generators

    Here I am building by hand.

    Define some types: Add article_type.rb in ‘types’ folder which will define ArticleType
    app/graphql/types/article_type.rb
    1
    2
    3
    4
    5
    6
    7
    
    ArticleType = GraphQL::ObjectType.define do
      name "Article"
      field :id, types.Int
      field :title, types.String
      field :body, types.String
      field :comments, types[CommentType]
    end
    
    Now we need to build schema, which is what we use to query
    app/graphql/types/query_type.rb
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    QueryType = GraphQL::ObjectType.define do
      name "Query"
      description "The query root of this schema"
    
      field :article do
        type ArticleType
        argument :id, !types.ID
        description "Find a Article by ID"
        resolve ->(obj, args, ctx) { Article.find_by_id(args["id"]) }
      end
    end
    
    This will query article by accepting ID as argument Then, build a schema with QueryType as the query entry point: Add following in graphql_ruby_sample_schema.rb
    app/graphql/graphql_ruby_sample_schema.rb
    1
    2
    3
    4
    
    # encoding: utf-8
    GraphqlRubySampleSchema = GraphQL::Schema.define do
      query QueryType
    end
    
    Since, we created new folders we have to tell Rails to autoload paths. Put below code in application.rb to autoload graphql and types folder like so:
    config/application.rb
    1
    2
    
    config.autoload_paths << Rails.root.join('app/graphql')
    config.autoload_paths << Rails.root.join('app/graphql/types')
    
    This schema is ready to serve GraphQL queries!. play around this query in GraphiQL.

    Here’s an example of a GraphQL query that a client can use to ask a server about the title of article #1:
    1
    2
    3
    4
    5
    
    query {
      article(id: 1){
        title
      }
    }
    
    Here’s a possible JSON response for that query:
    1
    2
    3
    4
    5
    6
    7
    
    {
      "data": {
        "article": {
          "title": "A GraphQL Server"
        }
      }
    }
    
    You can execute queries from a query string:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    query_string = "
    {
      article(id: 1) {
        id
        title
      }
    }"
    result_hash = GraphqlRubySampleSchema.execute(query_string)
    
    output:
    # {
    #   "data" => {
    #     "article" => {
    #        "id" => 1,
    #        "title" => "A GraphQL Server"
    #     }
    #   }
    # }
    
    You can see sample code here.

Comments