Ruby on Rails GraphQL API Tutorial: From 'rails new' to First Query
Tags: rails, graphql, api, tutorial
Published: 2019-09-16 01:12:33

---
title: "Ruby on Rails GraphQL API Tutorial: From 'rails new' to First Query"
published: true
description: a tutorial for creating a simple graphql api in rails
tags: rails, graphql, api, tutorial
series: "Ruby on Rails GraphQL API Tutorial"
---

This week, I've been working on a takehome technical challenge asking me to deep-dive into [GraphQL](https://graphql.org/learn/) and create a simple API. I've never worked with GraphQL before, so I opted to stick with Ruby on Rails for learning it.

This tutorial is designed to walk through the steps to create a GraphQL API with Ruby on Rails and the [Ruby gem 'graphql'](https://graphql-ruby.org/). 

**It is largely adapted from [this AMAZING tutorial by Matt Boldt](https://mattboldt.com/2019/01/07/rails-and-graphql/)**, with a few notable differences:
 * I will use the [Insomnia REST client](https://insomnia.rest/) for API calls instead of [the 'graphiql' IDE](https://github.com/graphql/graphiql) -- *if you don't already have it installed, go ahead and do that now!*
 
 * I will start with simple `Order` and `Payment` models, but eventually (in a future article) branch into more complicated relationships (and implementing features like filtering objects with custom methods directly on the model and `has_many` declaration)

 * I will explore **"idempotency"** in GraphQL as part of Mutations (in a future article), using strategies [covered in this EXCELLENT article by Todd Jefferson](https://engineering.shopify.com/blogs/engineering/building-resilient-graphql-apis-using-idempotency)



# Overview 
In this first article, we'll go through the steps to:
* create a Rails API
* add some models
* add GraphQL
* write and execute our first GraphQL Query

GraphQL has two ways of interacting with databases
1. **Query** -- this allows us to get data ("Read" in CRUD)
2. **Mutation** -- this allows us to change information, including adding, updating, or removing data ("Create", "Update", "Destroy" in CRUD)

We'll keep our focus on getting the API running, and understanding our first simple Query.

Let's dive in!


# What is GraphQL?
GraphQL is a query language we can use to get and mutate data in a database. It gives users a lot of control over what data you want to get back by targeting specific models and fields to return. It is also strongly typed, so you know exactly what kind of data you're receiving!

[Read more about GraphQL on the project's website.](https://graphql.org/learn/)

GraphQL is language-independent, so the Ruby implementation we will be using is the [Ruby gem 'graphql'](https://graphql-ruby.org/). This gives us a specific file structure and some command-line tools to easily add GraphQL functionality to our Rails API.



# Creating the Rails app

### 'rails new'
Run the following command in your terminal to create a new Rails project called **devto-graphql-ruby-api**. Feel free to leave out any of these --skip flags, but none of them will be used:

`$ rails new devto-graphql-ruby-api --skip-yarn --skip-action-mailer --skip-action-cable --skip-sprockets --skip-coffee --skip-javascript --skip-turbolinks --api`

### Generating models

Inside the directory, let's create our `Order` and `Payment` models:

```
$ rails g model Order description:string total:float
$ rails g model Payment order_id:integer amount:float
```

I prefer to set up my has_many-belongs_to relationships by hand, so let's make `Payment`s belong to an `Order`:

```ruby
# app/models/order.rb
class Order < ApplicationRecord
	has_many :payments
end
```

```ruby
# app/models/payment.rb
class Payment < ApplicationRecord
	belongs_to :order
end
```

### Create database
Run `$ rails db:create` to create the (default) SQLite3 development database.

### Run migrations
Run `$ rails db:migrate` to add our models to the database.

### Add seed data
Add a few example objects to seed our database:

```ruby
# db/seeds.rb
order1 = Order.create(description: "King of the Hill DVD", total: 100.00)
order2 = Order.create(description: "Mega Man 3 OST", total: 29.99)
order3 = Order.create(description: "Punch Out!! NES", total: 0.75)

payment1 = Payment.create(order_id: order1.id, amount: 20.00)
payment2 = Payment.create(order_id: order2.id, amount: 1.00)
payment3 = Payment.create(order_id: order3.id, amount: 0.25)
```
Then run `$ rails db:seed` to add the data to the database.

Now we're ready to start adding in GraphQL on top of our models!



# Adding GraphQL

### Add 'graphql' gem to Gemfile
```ruby
# Gemfile
gem 'graphql'
```
Then run `$ bundle install` to install the gem in the app.

###  Install GraphQL with 'rails generate'
Run `$ rails generate graphql:install`. This will add the `/graphql/ `directory to the app's main directory, as well as a GraphQL-specific controller at `/controllers/graphql_controller.rb`.

### Add GraphQL objects for models
We now need to create GraphQL objects to match our models:

`$ rails generate graphql:object order`
`$ rails generate graphql:object payment`



# Filling out the new GraphQL files
Okay, we now have all the files and directories needed to build our first Query! But, some of those files still need some more code.

### Define the GraphQL Types and their fields
GraphQL Types are defined with fields that tell us what data we can get from them:

```ruby
# app/graphql/types/payment_type.rb
module Types
	class PaymentType < Types::BaseObject
		field :id, ID, null: false
		field :amount, Float, null: false
	end
end
```
This allows us to retrieve `PaymentType` objects that contain an `id` field (with a special ID primary key), and an `amount` field that will be a Float. Because both are set to `null: false`, receiving a Query response with `nil` in either field will throw an error.

Our GraphQL objects inherit from Types::BaseObject. Thus, when we define our `class PaymentType < Types::BaseObject`, we now have a `Types::PaymentType` available. We can use these custom Types to define what we get back from each field.

Let's take a look at how we can use `Types::PaymentType` in `OrderType`:

```ruby
# app/graphql/types/order_type.rb
module Types
	class OrderType < Types::BaseObject
		field :id, ID, null: false
		field :description, String, null: false
		field :total, Float, null: false
		field :payments, [Types::PaymentType], null: false
		field :payments_count, Integer, null: false
		  
		def payments_count
			object.payments.size
		end
	end
end
```
Several things to note here:
* Because the `Order` model has columns for `id`, `description`, and `total`, we can simply create a field for them and retrieve their data.
* Because of our has_many-belongs_to relationship, we can also make a `payments` field to return all `Types::PaymentType` objects belonging to each `Order`.
* However, `Order` does NOT have a `payments_count` column--so we define a `payments_count()` method to return an integer with the length of the `payments` array. 
	* NOTE: inside these custom field methods, we need to access the `Order`'s `payments` through **`object.payments`**--don't forget that critical `object`!

### Define fields on QueryType
We're almost ready to write that first Query, but first, we need to tell the main QueryType to expect it. When GraphQL receives a Query request (as opposed to a Mutation request), it will be routed to the QueryType class. Like with the Types above, we will define possible Query methods through fields.

Our first Query will simply be to retrieve all `Order`s in the database. Inside the `class QueryType` declaration, we'll add a field that returns an array of `Types::OrderType`:

```ruby
# app/graphql/types/query_type.rb
module Types
	class QueryType < Types::BaseObject
		field :all_orders, [Types::OrderType], null: false
		  
		def all_orders
			Order.all
		end
	end
end
```
As above, we define our `all_orders()` method underneath the field with the same name, and tell it to implicity return all `Order`s.

Everything's now set! We can open up Insomnia and write our first Query to get all `Order`s back from the database.


# Writing our first Query

### GraphQL Query format
Here's what our first Query will look like:
```graphql
query {
	allOrders {
		id
		description
		total      
		payments {
			id
			amount
		}
		paymentsCount
    }
}
```

At the top, we define the request as a `query {}`.

Inside the query, we call the QueryType's `all_orders` via `allOrders {}`. Yep, don't forget to switch from snake-case to camel-case!

Inside `allOrders {}`, we select the fields from the `Order` model we want returned. These are the same fields we defined in `app/graphql/types/order_type.rb`. You can pick and choose which ones you want to receive!

Note that, with our `payments {}` field, we also have to define the fields from `Types::PaymentType` that we want to receive. The fields available are the ones we defined in `app/graphql/types/payment_type.rb`.

The `paymentsCount` field will run the `payments_count` method on `Types::OrderType`, and return the appropriate value.

Let's get this Query into Insomnia and test our API!

### Execute Query in Insomnia
Run `$ rails s` to start the Rails API server at [http://localhost:3000/graphql](http://localhost:3000/graphql).

Open Insomnia, and create a new POST request. In the top-left corner of the request text editor, make sure the the POST request's format is set to "GraphQL Query".

Go ahead and add the code from the `query` above. Then send it off, and see what it returns:

![screenshot of Insomnia running query and showing return data](https://thepracticaldev.s3.amazonaws.com/i/p57k51mvolx8j1ezvpj6.png)

Woo! Our data's all nice and organized--and it's exactly and ONLY what we requested!

Let's run a similar query, but with a fewer fields:

```graphql
query {
	allOrders {
		description
		total      
		payments {
			amount
		}
    }
}
```

Result:

![screenshot of Insomnia running query with fewer fields, and showing return data](https://thepracticaldev.s3.amazonaws.com/i/cf1vcwra6ofmt3yph6k9.png)

Perfect! If we don't need the `id`s or the `paymentsCount`, no need to include them in the Query at all!



# Conclusion

We now have a very simple API to Query data from a database using GraphQL! However, since GraphQL Queries can only *retrieve* data, we can't use our current code to make any *changes* to the database. 

That's where Mutations come in! We'll cover that in the next installment. ;)

[Here's the repo for the code in this article, too. Feel free to tinker around with it!](https://github.com/isalevine/devto-graphql-ruby-api)

And once again -- __*thank you*__ to Matt Boldt and [his AWESOME Rails GraphQL tutorial](https://mattboldt.com/2019/01/07/rails-and-graphql/) for helping me get this far! <3

Any tips or advice for using GraphQL in Rails, or GraphQL in general? Feel free to contribute below!