GraphQL - What Is It?
I had barely been exposed to GraphQL when I was first asked to cover it over on the Deanin YouTube channel. My only experience was a brief demo done in one of my IT classes in College. Not one to shy away from a challenge, however, I finally decided to tackle it.
But what actually is GraphQL? Well, according to its website:
GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, 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.
It’s always interesting trying a new tech like GraphQL inside of Ruby on Rails. It almost always adds an additional layer of complexity, and demystifying it can be a challenge. Thankfully I managed to stumble my way through my first application in about 5 days though. Hopefully this blog post can serve as a starting point for you to try GraphQL as well.
Video Version Of This Tutorial
I’m including video timestamps again just in case you want to skip to a specific part and save some time!
0:00 Video Overview & Intro
2:30 Create Ruby On Rails With GraphQL App
8:04 Creating Models For GraphQL To Use
11:00 GraphQL Generators inside of Ruby on Rails 6
12:52 GraphQL Types For Queries
19:46 GraphQL Mutators For Data Creation
25:25 Bug Fixes
27:45 GraphQL Demo With Example Queries And Mutations
35:35 Video Summary & Outro
Part 1 - Creating The Rails App
We’re going to be moving pretty quick here, because it’s late and the actual commands and code aren’t too bad. First we’re going to create the Rails app and do some basic GraphQL setup by adding gems. We’ll run some installers, create and modify a few files, and run some model generators. I’ll add comments to the code so you know which file to create/modify for each line.
# In your terminal, run:
rails new graphql-postapp --api --skip-test --skip-spring
cd graphql-postapp
bundle add graphql
bundle add graphiql-rails
rails g graphql:install
rails g model Post title body:text
rails g model Author name
rails g migration add_author_to_posts author:references
rails db:migrate
# Next, open up a rails console and create an author.
# In your terminal, type:
rails c
author = Author.new
# Change Dean to whatever you want
author.name = "Dean"
author.save
# Press CTRL + D to exit the rails console.
Next, inside of your application, create the typical assets folder inside of /app. Inside of that assets folder, create a config folder. Finally, inside of that config folder you’ll want to create a manifest.js file and include the following links. Afterwards, you’ll need to modify your /config/application.rb file.
# config/application.rb
# uncomment the following
require "sprockets/railtie"
# Inside your routes.rb file, configure GraphiQL
Rails.application.routes.draw do
if Rails.env.development?
mount GraphiQL::Rails::Engine, at: "/graphiql", graphql_path: "/graphql"
end
post "/graphql", to: "graphql#execute"
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
Part 2 - Creating The GraphQL Types
Next up we’re going to be running some GraphQL generators. These will create the necessary files inside of your graphql folder in your project. There’s two types of actions to worry about: Queries and Mutations. The queries we create will be to retrieve data. The mutations are to create, update, or destroy data.
# In your terminal, run the following to create your types
rails g graphql:object Post
rails g graphql:object Author
# Run these commands to create your mutations
rails g graphql:mutation CreateAuthorMutation
rails g graphql:mutation CreatePostMutation
# Next, in app/graphql/types/query_type.rb
# change it to match the following:
module Types
class QueryType < Types::BaseObject
field :posts, [Types::PostType], null: false do
description "Query that selects all posts."
end
field :postsCount, Integer, null: false do
description "Query that returns the total number of posts."
end
def posts
return Post.all
end
def postsCount
return Post.count
end
end
end
Next we’ll have to create both the PostType and the AuthorType. We’ll be adding descriptions to our data. This makes it easier to see inside localhost:3000/graphiql what code does what. If you add a description to a var and it shows up describing a thing in a query, you know that file is for queries!
# graphql/post_type.rb
module Types
class PostType < Types::BaseObject
field :id, ID, null: false do
description "This post's id."
end
field :title, String, null: true do
description "This post's title."
end
field :body, String, null: true do
description "This post's body, the main content of the post."
end
field :created_at, GraphQL::Types::ISO8601DateTime, null: false do
description "The date/time that this post was created at."
end
field :updated_at, GraphQL::Types::ISO8601DateTime, null: false do
description "The date/time that this post was last updated at."
end
field :author_id, Integer, null: false do
description "The id of this post's author."
end
field :author, AuthorType, null: true do
description "This post's author in object form."
end
end
end
# graphql/author_type.rb
module Types
class AuthorType < Types::BaseObject
field :id, ID, null: false
field :name, String, null: true
field :post, [PostType], null: true
field :created_at, GraphQL::Types::ISO8601DateTime, null: false
field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
end
end
Part 3 - GraphQL Mutations!
For this next part we’ll be creating the post mutation. I’ve left the author mutation intentionally blank so that you have something to practice with. In all honesty, you could just mostly copy paste from post mutation to get this working. That said, copy pasta is how I got this far in life, so it should help you too haha.
# Inside graphql/create_post_mutation.rb
module Mutations
class CreatePostMutation < BaseMutation
field :post, Types::PostType, null: false
argument :title, String, required: true do
description "The title field is a string type and is required for a new Post to be created."
end
argument :body, String, required: true do
description "This is the post's main content, it is called the body and it expects a string."
end
argument :author, Integer, required: true do
description "The id of this post's author."
end
def resolve(title:, body:, author:)
@post = Post.new(title: title, body: body, author: Author.find_by_id(author))
if (@post.save)
{
post: @post,
errors: []
} else {
post: nil,
errors: @post.errors.full_messages
}
end
end
end
end
# Inside graphql/create_author_mutation.rb
module Mutations
class CreateAuthorMutation < BaseMutation
# TODO: define return fields
# field :post, Types::PostType, null: false
# TODO: define arguments
# argument :name, String, required: true
# TODO: define resolve method
# def resolve(name:)
# { post: ... }
# end
end
end
Part 4 - Some Example GraphQL Queries And Mutations
So you made it this far and now you’re wondering, “Dean, How do I test this GraphQL app and actually use it?” Well don’t worry, because if there’s one thing I’m great at it’s answering easy questions to seem like an expert! I’ll include the example queries as well as instructions on how to execute them from what we did in the video. Hopefully this answers your questions a bit.
Just remember though, the reason why your application works is because we manually created that one author! You’ll want to mutate a few extra authors and set up your author mutations/types for more advanced functionality. This will probably mirror what we did in posts quite a bit!
# Inside your terminal, run:
rails s
# Then open a browser and navigate to localhost:3000/graphiql
# That's graphiql, not graphql. Remember the i!
# In your browser, you can run the following mutation to create a post or two:
mutation {
createPostMutation(input: {
title:"Test",
body:"test",
author:1
}) {
post {
authorId,
title,
body
}
}
}
# And you can run variations of this query to query your GraphQL Database
query {
postsCount,
posts {
title,
body,
authorId,
author {
id,
name
}
},
}
Conclusion - GraphQL Is Awesome!
So there you have it, that’s what I came up with while learning GraphQL this week! I’m really impressed with the technology and happy with how much I’ve learned the last 5 days. It’s amazing how much a little API wrapper thing can do.
I’m hoping to maybe carry GraphQL into an upcoming week of the 20in20 Challenge project. Maybe do something with some more advanced mutations and queries. Hey, maybe I’ll even learn enough to get Devise working with GraphQL! Well, thanks for your time and I hope this helped. Until next time, Deanout.