GraphQL and Relay on Rails — Getting Started

Gaurav Tiwari
Statuscode
Published in
6 min readDec 26, 2015

Introduction: These series of posts explores how to integrate GraphQL with Rails stack on the server side and Relay on the client side for a building a demo Medium like blog application. The idea to use standard Rails stack and see how far we can go without changing much of our standard stack.

Pre-requisites: Ruby and Rails stack in general. You should also know and understand React.

Before starting the application, lets briefly look at what is GraphQL and Relay:

GraphQL

A GraphQL system or server exposes an application to the world according to its schema. A schema can be compared with a relational database schema, it contains the definition or name in the form of types and information about entities that are available to be read and modified.

Based on the GraphQL Schema, the connected applications read and modify states of the system. For simplicity, imagine it like a database with set of tables that makes up the Schema, but also keep in mind that this is an extra layer on top of the application and not connected to database.

Note: The GraphQL server has a single entry point for all data needs compared to a REST API, which would be something like: api.example.com with multiple endpoints /posts/1 or post/1/comments/.

Note: The word GraphQL may be confusing and may refer to Graph databases, but really you can use this layer with any database.

A GraphQL schema includes:

  • Types which expose objects in your application, in other words a model or table of your application. For ex: PostType
  • Fields which expose properties of those objects (and may associate types to other types), in other words fields of a model or a table. For ex: Title of the post
  • Query root, which is a special type used for executing read queries, in other words reading a collection of data from a model or a table. For ex: Posts, which fetches all posts or PopularPosts, which gets only popular posts
  • Mutation root, which is a special type used for executing mutations, in other words changing states of a model or a table. For ex: Creating, Editing or Deleting Records from a table or Store
A comment type that exposes following fields from a given model

The above is a CommentType that exposes specific comment properties to be accessed using GraphQL server. Don’t worry if this doesn’t make sense we will go through this in more detail later.

Generated documentation for Comment

Note: We are writing descriptions as we are exposing the fields through GraphQL server, which means we don’t have to write any extra API documentation like we do for REST APIs.

The GraphQL server will generate documentation during build process and will be saved into the Schema.

Relay

Relay on the client side lets each react component declare its own data requirements in the form of a GraphQL query fragment.

A very simple query fragment would look something like this:

A GraphQL query fragment to fetch a single comment for rendering

Here is a react component that wants to render a single comment and in order to do so: it needs the body of the comment, the date it was created at and it’s associated user name.

If you have worked with relational databases before this may look very familiar:

SELECT "comments"."created_at", "comments"."body" FROM "comments"

In this above case however, a component is declaring it’s data requirements in the view using Relay and then Relay communicates this to GraphQL server through the defined Schema. This makes the data queries live next to the views that rely on them, so we can easily see and reason about the app.

The server will return following JSON response:

Returns this response

Relay also caches data and aggregates queries into efficient network requests to fetch only what a component needs. You can read more about GraphQL and Relay on its official website to get a better understanding.

  1. GraphQL
  2. Relay

Lets now look at the application we will be building throughout a series of posts.

The Application

We will be building a simple demo blog application, like medium throughout a series of posts (don’t know how many). So, lets set some standard expectations to get started.

Here is a set of features we will be implementing:

  1. As a user I want to see a list of posts.
  2. As a user I want to scroll the page to load more posts and comments.
  3. As a user want to click on post title and go to post show page.
  4. As a user I want to see post comments on post show page.
  5. As a user I want to filter posts and comments by: date, popularity and votes.
  6. As a user I want to create a account and login.
  7. As a logged in user I want to vote up a post and comment.
  8. As a logged in user I want to comment on a post.

Lets keep it up to this for now we can add features as we go along.

Part 1

In part 1 of this series, we will setup our rails application and install necessary gems needed for graphql and relay integration. We will also setup browserify using browserify-rails gem to use node modules within our Rails application asset pipeline. Browserify lets us require(‘modules’) in the browser by bundling up all the dependencies.

Lets create a brand new rails 4.2.5 application:

rails new blog -d postgresql -T
cd blog

Open the application into your editor and paste below text into your Gemfile and bundle the gems.

ruby ‘2.2.3’
source ‘https://rubygems.org'
# Setup Rails with postgresql database
gem ‘rails’, ‘4.2.5’
gem ‘pg’
# Setup passenger as server
gem ‘passenger’
# Asset compilation and NPM modules
gem ‘browserify-rails’, ‘1.5.0’
gem ‘sass-rails’
gem ‘uglifier’
# Setup react and dependencies
gem ‘therubyracer’, platforms: :ruby
# Graphql and Relay integration into Rails
gem ‘graphql’
gem ‘graphql-relay’
# Javascript routes
gem ‘js-routes’
# JQuery turbolinks
gem ‘jquery-turbolinks’
# User authorization
gem ‘pundit’
# User authentication
gem ‘devise’
# Bootstrap
gem ‘bootstrap-sass’, ‘~> 3.3.6’
# Speed up links
gem ‘turbolinks’, github: ‘rails/turbolinks’
# Slug title
gem ‘stringex’
# Time
gem ‘local_time’
# React integration
gem ‘react-rails’, ‘~> 1.5.0’
# Asset Caching
gem ‘rack-cache’
gem ‘kgio’
gem ‘dalli’
# Fake data
gem ‘faker’
group :production do
gem ‘rails_12factor’ # Heroku deployment
end
group :development do
gem ‘spring’
gem ‘web-console’
gem ‘foreman’
gem ‘figaro’
end

We are using graphql-ruby & graphql-relay-ruby gems for using GraphQL schema in Ruby and getting Rails to speak GraphQL.

Now, lets setup browserify for client side dependencies so, that we can require node modules within our react components. Create a file called package.json under the main app directory blog/ and paste below text and run: npm install to install node modules.

{
"name": "Blog",
"dependencies": {
"babel-plugin-syntax-jsx": "^6.3.13",
"babel-relay-plugin": "0.6.0",
"babel-relay-plugin-loader": "^0.6.0",
"babelify": "^7.2.0",
"browserify": "^12.0.1",
"browserify-incremental": "^3.0.1",
"browserify-shim": "^3.8.11",
"classnames": "^2.2.1",
"graphiql": "^0.4.5",
"graphql": "^0.4.14",
"isomorphic-fetch": "^2.2.0",
"jquery": "^2.1.4",
"jquery-ujs": "^1.0.4",
"react": "^0.14.3",
"react-dom": "^0.14.3",
"react-relay": "^0.6.0",
"babel-preset-es2015": "^6.1.18",
"babel-preset-react": "^6.1.18"
},
"license": "MIT",
"engines": {
"node": ">= 4.2.2"
},
"devDependencies": {
"browserify-incremental": "^3.0.1"
},
"metadata": {
"graphql": {
"schema": "./app/assets/javascripts/relay/schema.json"
}
}
}

Once the client side dependencies are installed, go to app/assets/javascripts and create a folder called relay and inside that folder create a file named schema.json. We have discussed a little bit about Schema in the introduction section, but we will discuss in detail in our next post.

Lets finally install react-rails gem:

# From terminal run
rails g react:install

Now, we are all set to start creating Schema and GraphQL server on Rails.

In second post, we will setup the GraphQL types for our application to create a Schema and then look into how to execute that Schema to query the GraphQL server.

Stay tuned!

Update: Lately, the project was updated to use Webpack to make things simpler so, please checkout this post: https://medium.com/@gauravtiwari/graphql-and-relay-on-rails-moving-to-webpack-9c6a420b4eea#.up15fv7em

--

--