Ruby on Rails API and Graph QL
By: Aaron Schuyler
Tags: Ruby on Rails, GraphQL, API, Rails

class GraphqlController < ApplicationController

# If accessing from outside this domain, nullify the session

# This allows for outside API access while preventing CSRF attacks,

# but you'll have to authenticate your user separately

# protect_from_forgery with: :null_session def execute

variables = prepare_variables(params[:variables])

query = params[:query]

operation_name = params[:operationName]

context = {

# Query context goes here, for example:

# current_user: current_user,

}

result = GraphQlApiTestProjectSchema.execute(query, variables: variables, context: context, operation_name: operation_name)

render json: result

rescue => e

raise e unless Rails.env.development?

handle_error_in_development e

end private # Handle variables in form data, JSON body, or a blank value

def prepare_variables(variables_param)

case variables_param

when String

if variables_param.present?

JSON.parse(variables_param) || {}

else

{}

end

when Hash

variables_param

when ActionController::Parameters

variables_param.to_unsafe_hash # GraphQL-Ruby will validate name and type of incoming variables.

when nil

{}

else

raise ArgumentError, "Unexpected parameter: #{variables_param}"

end

end def handle_error_in_development(e)

logger.error e.message

logger.error e.backtrace.join("

") render json: { errors: [{ message: e.message, backtrace: e.backtrace }], data: {} }, status: 500

end

end

Essentially what is happening is the GraphQL boilerplate in the controller is taking any variables and the query and going through the GraphQl engine to grab that info from the DB. All of our GraphQL queries are accessed through the same route, '/graphql' and go through this execute method.

Thankfully we do not need to modify this code at all. Our focus will be on the code found in the app/types folder.

Let’s look at app/graphql/query_type.rb

module Types

class QueryType < Types::BaseObject

# Add root-level fields here.

# They will be entry points for queries on your schema. # TODO: remove me

field :test_field, String, null: false,

description: "An example field added by the generator"

def test_field

"Hello World!"

end

end

end

Let’s spin up postman and test this out! open a new tab, change the type to post, set the url (in my case it is ‘https://localhost:3000/graphql’ and that should be the same for you).

Next you should click the body tab and select GraphQl from the dropdown list. Add the following to the query box:

{

testField

}

This should be what you see after submitting.

Let’s set it up so we can get our users with GraphQL. In query_type.rb remove the demo stuff and add code to get the following:

module Types

class QueryType < Types::BaseObject

field :users,

[Types::UserType],

null: false,

description: 'get Users' def users

User.all

end

end

end

Now run this query in postman:

{

users {

id,

username,

email

}

}

and you should get this result:

Wow! So soon you ask yourself? Why yes, it is that easy! Hold on to your horses because this is where it gets cool!

What if we want to get the posts?

Let’s modify query_type.rb further to include:

module Types

class QueryType < Types::BaseObject

field :users,

[Types::UserType],

null: false,

description: 'get Users' # new code

field :posts,

[Types::PostType],

null: false,

description: 'get Posts' def posts

Post.all

end

# end new code def users

User.all

end

end

end

Let’s nest the user in each post! In app/graphql/types_post/type.rb change the following line:

module Types

class PostType < Types::BaseObject

field :id, ID, null: false

field :title, String, null: true

field :content, String, null: true # remove the following line

# field :user_id, Integer, null: false

# add the next line

field :user, Types:UserType, null:false field :created_at, GraphQL::Types::ISO8601DateTime, null: false

field :updated_at, GraphQL::Types::ISO8601DateTime, null: false

end

end

Now if you add the user to the posts query you can see the results in action:

Last but not least, let’s grab a post by ID with GraphQL! Add the following new code to your query_type.rb

module Types

class QueryType < Types::BaseObject

field :users,

[Types::UserType],

null: false,

description: 'get Users' field :posts,

[Types::PostType],

null: false,

description: 'get Posts'



# new code

field :post, Types::PostType, null: false do

argument :id, ID, required: true

description 'find post by id'

end def post(id:)

Post.find(id)

end

# end new code def posts

Post.all

end def users

User.all

end

end

end

In Postman you should set up the query like this:

query ($id: ID!) {

post (id: $id) {

title,

content,

user {

username

}

}

}

Below the query you can add your variable which is what $id is.

{

"id": 1

}

Basically we are saying we have a variable id with a value of 1 and the datatype is ID the ! in ID! denotes that this is a required parameter.

You should see desirable results in Postman when submitting this query:

Congrats! You set up a rails API with GraphQL. Happy coding.

Here is a part 2 to this guide!

More guides coming soon!