How to Create a GraphQL API With Ruby on Rails: A Step-by-Step Guide - Part 1
Tags: rails, graphql, tutorial, ruby
Published: 2024-01-16 22:59:25

In the ever-evolving world of Ruby on Rails web development, the adoption of GraphQL has taken a leading role due to its flexibility and efficiency in creating APIs. In this article, I'll walk you through a step-by-step approach to integrating GraphQL into a Rails project focused on **articles** and **comments**. From initial setup to creating specific queries and resolvers, we'll explore together how to leverage the power of GraphQL in our application.


#### Creating the Rails Application and Configuring GraphQL

Before we dive into the fascinating world of GraphQL, make sure you have your development environment up and running.

Let's start by creating a new Rails application and configuring GraphQL. Let's run the following commands to start our project:

```
rails new articles-graphql-app
cd articles-graphql-app
bundle add graphql
```

This set of commands sets the basics for integrating GraphQL into our application:

* `rails new articles-graphql-app`: This command creates a new Rails application named "articles-graphql-app".

* `cd articles-graphql-app`: This command changes the current working directory to the newly created "articles-graphql-app" directory. Move inside the project folder to perform specific actions in that context.

* `bundle add graphql`: Adds the graphql gem to your project's Gemfile. The graphql gem provides the necessary tools to implement GraphQL in your Rails application.

Now let's run the `rails generate graphql:install` command in the root of the project which sets up the basic infrastructure for GraphQL in your Rails application. It organizes your GraphQL code into specific folders, making it easier to manage and scale as you add more functionality to your GraphQL API, generating the following points:

* Route for GraphQL that adds a new route in your `config/routes.rb` file that maps the `/graphql` URL to the generated GraphQL driver. This route acts as the entry point for GraphQL requests.


* Controller named `GraphqlController` in the `app/controllers` directory. This controller is responsible for handling GraphQL requests and orchestrating the execution of queries and mutations.

* Folder `app/graphql` in which all related GraphQL files will be organized. Within `app/graphql`, specific subfolders are created to organize different components:
  * **mutations**: Here you can define and manage GraphQL mutations that modify data in your application.
  * **resolvers**: In this folder, you can implement resolvers that handle GraphQL queries and mutations. The resolvers are responsible for obtaining and returning the requested data.
  * **types**: Contains the definitions of GraphQL types that represent your models and data structures in the application.

#### Generating models and data for Post and Comment models

To be able to interact with the models you must generate the models and data. In this case you are going to use a gem called `faker`. We will run the following command to add the gem to the Gemfile

```
bundle add faker
```

**Faker** is a useful tool to generate dummy data in a realistic way, which will ease the creation of test data for your article and comment models.

Now you are going to generate the model for **Post** that includes two fields: **title** of type string and **content** of type text. This model will represent the articles in the application.

```
rails generate model Post title:string content:text
```

Now you are going to generate the **Comment** model that includes a text content field and establishes a **belongs_to** association with the **Post** model. This will allow each comment to be linked to a specific article in our application.

```
rails generate model Comment post:belongs_to content:text
```

You must set the reverse relationship in the Post model. Open the `app/models/post.rb` file and add the line `has_many :comments` to indicate that an article can have many comments. Your `app/models/post.rb` file might look something like this:

```ruby
class Post < ApplicationRecord
  has_many :comments
end
```

Now let's edit the `db/seeds.rb` file so that you can create 20 articles, each with a generated fake title and three related comments, each with fictitious content. The script should look like this:

```ruby
require 'faker'


20.times do
  post = Post.create(
    title: Faker::Lorem.sentence
  )
  3.times do
    Comment.create(
      post: post,
      content: Faker::Lorem.paragraph
    )
  end

end

puts 'Seed data created successfully!'
```
To run the seed script, simply place this code in the `db/seeds.rb` file. Then, you can run the following commands to ensure that all the data has been created as expected:

```
rails db:migrate
rails db:seed
```

Ready to move on to the next steps?  🚀

#### Setting Resolvers for Posts

Basically a resolver is a function that handles the logic to obtain the data requested by a GraphQL query or mutation. In other words, a resolver answers the question "how to get this specific data?".

Now let's set up resolvers and GraphQL types to handle specific queries. Add this line to `app/graphql/types/query_type.rb`:

```ruby
field :posts, resolver: Resolvers::PostsResolver
```

To display the file `app/graphql/types/query_type.rb` like this:

```ruby
module Types
  class QueryType < Types::BaseObject
    description "The query root of this schema"

    field :posts, resolver: Resolvers::PostsResolver
  end
end
```

By adding the `:posts` field to your GraphQL query type (`QueryType`) and associating it with the `Resolvers::PostsResolver`, you are configuring GraphQL to handle posts queries. This resolver will take care of getting and returning the necessary information when a posts query is performed.

Now we're going to create the resolver to get all the posts in `app/graphql/resolvers/posts_resolver.rb`:

```ruby
module Resolvers
  class PostsResolver < BaseResolver
    type [Types::PostType], null: false

    def resolve
      ::Post.all
    end
  end
end
```

#### Setting Types for Posts and Comments

To give some context, a Type refers to the data structure that you can query or modify using the GraphQL query language. In GraphQL, types represent the entities in our system and define the fields that can be queried or mutated on those entities.

Now let's define the post type in `app/graphql/types/post_type.rb`:

```ruby
class Types::PostType < Types::BaseObject
  field :id, ID, null: false
  field :title, String, null: false
  field :content, String, null: false
  field :comments, [Types::CommentType],
      description: "This post's comments, or null if this post has comments disabled."
end
```
By creating the PostType type in `app/graphql/types/post_type.rb`, you are defining how it will be structured and what fields will be available when information about a post is requested through GraphQL. This PostType type includes fields such as id, title, and content, and also provides a comments field that represents the comments associated with that post.

With the post type definition in place, your GraphQL schema now has a clear representation of how posts are structured and their relationships to other types.

Now let's define the comment type in `app/graphql/types/comment_type.rb`:

```ruby
class Types::CommentType < Types::BaseObject
  field :id, ID, null: false
  field :post, Types::PostType, null: false
  field :content, String, null: false
end
```

In this CommentType type, you are specifying that a comment has fields such as id, post, and content. The post field represents the relationship between a comment and the post it belongs to, using the PostType type you defined earlier.

With the comment type definition in place, you now have a more complete GraphQL schema that clearly represents the structure of your data


#### Testing the Posts API

After setting up our GraphQL API for Posts, execute your `rails server` and now you can test it using cURL directly from the command line or with more visual tools like Postman:
```
curl --location 'http://localhost:3001/graphql' \
--header 'Content-Type: application/json' \
--data '{"query":"query {\n  posts {\n    id\n    title\n    comments {\n        id\n        content\n    }\n  }\n}\n","variables":{}}'

```
In Postman, for example, the result should look like this:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rx1ks69nbzwp834u1hrv.png)


In this journey through implementing GraphQL in a Ruby on Rails application, we've covered everything from initial setup to creating GraphQL resolvers and types to handle specific queries. GraphQL gives us the flexibility to request exactly the data we need, resulting in more efficient and tailored APIs.

We've explored creating types, resolvers and how to test our queries using cURL and Postman. Now with a solid foundation, but in the **next** post we will add to our schema GraphQL includes an additional query called post, which uses the Resolvers::PostResolver resolver to handle retrieving a specific post by its id.