Skip to content

RuthNjeri/GraphQL-Ruby-Training

Repository files navigation

Basic Ruby GraphQL Implementation.

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.

What I Managed To Implement.

  • A query to get all movies.
  • A query to get one movie.
  • A mutation to create a movie.

What is GraphQl and Why GraphQL.

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 and Installation

  • 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 or bundle update
  • Run rails generate graphql:install. This adds another gem gem 'graphiql-rails', group: :development and you need to run bundle install for it.

Creating the Movie Application

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 is null: 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 the app/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 in learning-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
  }}

References