I followed a tutorial from Unicorn Agency which shows an old syntax for implementing GrahpQL. Therefore, I also used a tutorial from How To GraphQL to implement the project in the recent syntax.
- A query to get all movies.
- A query to get one movie.
- A mutation to create a movie.
What? According to Suraj Kumar Paul, it is a query language for APIs and server-side runtime for executing queries.
Why? It allows the frontend to query the backend using a single endpoint, as compared to REST which is bulky.
- Set up Ruby
gem install bundler
gem install rails
bundle install
rails new learning-graphql
rails new db:create
- Run
rails s
to ensure the application is running - Stop the rails server
- Open the Gemfile and add this
gem 'graphql'
. The version used for this is'1.8.13'
- Run
bundle install
orbundle update
- Run
rails generate graphql:install
. This adds another gemgem 'graphiql-rails', group: :development
and you need to runbundle install
for it.
Application Set Up
rails generate model movie title description
rails db:migrate
- Create dummy data for the application within the db/seeds.rb file by adding this into the file
Movie.create(
title: ‘Deadly Weapon’,
description: ‘2 retired monks walk into a bar’
)
Movie.create(
title: ‘Deadly Weapon 2 — This time time it’s personal’,
description: ‘Like Deadly Weapon, only deadlier and more personal’
)
- Run
rails db:seed
to create the data.
GraphQL Implementation
- Create new file
/learning-graphql/app/graphql/types/movie_type.rb
. This is to define the GraphQL Type. Add the code below to that file. movie_type
(object type) is a basic component of the GraphQL schema. Representing an object(movies model) you can fetch from your service and what fields it has.fields
show fields that can appear in the object(movie_type) when a query is made.null
is included to show if a field is nullable or not, meaning when it isnull: false
GraphQL will always give a value for this.String
is a built in scalar type.
module Types
class MovieType < BaseObject
field :id, ID, null: false
field :title, String, null: false
field :description, String, null: false
field :created_at, Types::DateTimeType, null: false
end
end
- Ensure you have a
DateTimeType
by creating a file in/learning-graphql/app/graphql/types/date_time_type.rb
with the code:
module Types
class DateTimeType < Types::BaseScalar
def self.coerce_input(value, _context)
Time.zone.parse(value)
end
def self.coerce_result(value, _context)
value.utc.iso8601
end
end
end
- Next is to write the resolver. Each field in the GraphQL type requires a resolver. This begins by creating a GraphQL query.
- This previously ran command
rails generate graphql:install
created theapp/graphql/types/query_type.rb
- Edit this file
app/graphql/types/query_type.rb
to:
module Types
class QueryType < BaseObject
# Add root-level fields here.
# They will be entry points for queries on your schema.
field :all_movies, [MovieType], null:false
def all_movies
Movie.all
end
field :movie, MovieType, null:false do
argument :id, ID, required: true
end
def movie(id: nil )
Movie.find(id)
end
end
end
- Test the current implementation by running
rails s
and viewing http://localhost:3000/graphiql on the browser. - The Docs link on the top right contains the documentation of the application's schema. This is created due to a functionality called Introspection
- On the left pane, input a query:
{
allMovies {
id
title
description
createdAt
}
}
Then hit the play button to view the details of this query from the method all_movies
which is automatically converted to camelCase.
- The
movie
method allows querying a specific ID. On the left pane input the query and click the play button:
{
movie(id: 2) {
id
title
}
}
- Next is the mutation. A Query is for fetching a mutation is for editing the database..like a POST.
- The
MutationType
was autogenerated inlearning-graphql/app/graphql/types/mutation_type.rb
. - Expose this
MutationType
in the/learning-graphql/app/graphql/learning_graphql_schema.rb
if it is not already exposed.
class LearningGraphqlSchema < GraphQL::Schema
query Types::QueryType
mutation Types::MutationType
end
- Create a resolver for
CreateMovie
by creating a new file/learning-graphql/app/graphql/mutations/create_movie.rb
add the code
module Mutations
class CreateMovie < BaseMutation
argument :title, String, required: true
argument :description, String, required: true
type Types::MovieType
def resolve(title:nil, description:nil)
Movie.create!(
title: title,
description: description)
end
end
end
- Create
BaseMutation
in the file/learning-graphql/app/graphql/mutations/base_mutation.rb
and add the code.
class BaseMutation < GraphQL::Schema::Mutation
null false
end
end
- Expose the above mutation in
/learning-graphql/app/graphql/types/mutation_type.rb
module Types
class MutationType < BaseObject
field :create_movie, mutation: Mutations::CreateMovie
end
end
- Restart the rails server and head over to the GraphQL IDE in the browser and run the mutation in the left pane
mutation{ createMovie(title: "Deadly Weapon 3", description: "Even deadlier!") {
id
}}