Resources

Download Source Code

Summary

# Terminal
rails g graphql:install
rails g model User first_name last_name email birthdate:date

curl -XPOST -d 'query={ user(id: 2){first_name}}' http://localhost:3000/graphql
curl -XPOST -d 'query={ all_users{id first_name} }' http://localhost:3000/graphql

# Gemfile
gem 'graphql'
gem 'graphiql-rails', group: :development

# config/routes.rb
Rails.application.routes.draw do
  if Rails.env.development?
    mount GraphiQL::Rails::Engine, at: "/graphiql", graphql_path: "/graphql"
  end

  post "/graphql", to: "graphql#execute"
end

# GraphQL Query
# Test Field

{
  testField
}

# All Users and User with ID #1

{
  allUsers{
    id
    email
  }
  user(id: 1){
    first_name
  }
}

# Creating User and returning fields

mutation {
  createUser(input: {
    first_name: "John"
    last_name: "Smith"
    email: "john.smith@example.com"
    birthdate: "1980-01-31"
  }) {
    user {
      id
      first_name
      email
      birthday
    }
  }
}

# graphql_controller.rb
class GraphqlController < ApplicationController
  skip_before_action :verify_authenticity_token
  def execute
    variables = ensure_hash(params[:variables])
    query = params[:query]
    operation_name = params[:operationName]
    context = {
      # Query context goes here, for example:
      # current_user: current_user,
    }
    result = IntroductionToGraphQlSchema.execute(query, variables: variables, context: context, operation_name: operation_name)
    render json: result
  end

  private

  # Handle form data, JSON body, or a blank value
  def ensure_hash(ambiguous_param)
    case ambiguous_param
    when String
      if ambiguous_param.present?
        ensure_hash(JSON.parse(ambiguous_param))
      else
        {}
      end
    when Hash, ActionController::Parameters
      ambiguous_param
    when nil
      {}
    else
      raise ArgumentError, "Unexpected parameter: #{ambiguous_param}"
    end
  end
end

# app/graphql/types/query_type.rb
Types::QueryType = GraphQL::ObjectType.define do
  name "Query"
  # Add root-level fields here.
  # They will be entry points for queries on your schema.

  # TODO: remove me
  field :testField, types.String do
    description "An example field added by the generator"
    resolve ->(obj, args, ctx) {
      "Hello World!"
    }
  end

  field :user do
    type Types::UserType
    description 'Find user by ID'
    argument :id, !types.ID
    resolve ->(obj, args, ctx) {
      User.find(args['id'])
    }
  end

  field :all_users do
    type types[Types::UserType]
    description 'All users'
    resolve ->(obj, args, ctx) {
      User.all
    }
  end
end

# app/graphql/types/mutation_type.rb
Types::MutationType = GraphQL::ObjectType.define do
  name "Mutation"

  # TODO: Remove me
  field :testField, types.String do
    description "An example field added by the generator"
    resolve ->(obj, args, ctx) {
      "Hello World!"
    }
  end

  field :createUser, field: Mutations::CreateUser.field
end

# app/graphql/types/user_type.rb
Types::UserType = GraphQL::ObjectType.define do
  name 'User'
  field :id, !types.ID
  field :first_name, types.String
  field :last_name, types.String
  field :email, types.String
  field :birthday, types.String, property: :birthdate
end

# app/graphql/mutations/create_user.rb
module Mutations
  CreateUser = GraphQL::Relay::Mutation.define do
    name 'CreateUser'
    input_field :first_name, !types.String
    input_field :last_name, types.String
    input_field :email, types.String
    input_field :birthdate, types.String

    return_field :user, Types::UserType

    resolve ->(obj, args, ctx) {
      user = User.create do |user|
        user.first_name = args['first_name']
        user.last_name = args['last_name']
        user.email = args['email']
        user.birthdate = args['birthdate']
      end
      { user: user }
    }
  end
end