Ruby On Rails and GraphQL Part 2
By: Aaron Schuyler
Tags: Ruby on Rails, GraphQL, API, Backend Development

As a second installment to my last post, here is a guide on how to use GraphQL to get all posts by a user and how to get all comments with our post.

First off, we need to create a comments table:

rails g resource Comment content:text user:references post:references rails db:migrate

Now we need to go in and add the has_many part of the relationships with the posts and users:

# /app/models/post.rb class

Post < ApplicationRecord

belongs_to :user

has_many :comments

end #app/models/user.rb

class User < ApplicationRecord

has_many :posts

has_many :comments

end

Next we need to run a GraphQL generator:

rails g graphql:object comment

After that generator, we should be able to see a new type in /app/graphql/types named comment_type.rb. Let’s edit post_type.rb to add our comments to it.

# /app/graphql/types/post_type.rb

module Types

class PostType < Types::BaseObject

field :id, ID, null: false

field :title, String, null: true

field :content, String, null: true

field :user, Types::UserType, null: false

# new code

field :comments, [Types::CommentType], null: true

# end new code

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

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

end

end

The brackets around the type tell GraphQL that we want an array of comments, not just one, which makes sense with our has_many relationship.

If you followed the last guide, we generated some posts already, so lets add some comments to that. In the console run the following:

rails c

Comment.create(post_id: 1, content: ‘this is a comment’, user_id: 1)

Comment.create(post_id: 2, content: ‘this is a comment’, user_id: 1)

Comment.create(post_id: 1, content: ‘this is another comment by a different user’, user_id: 2)

Now if you submit the following GraphQL query:

{

posts {

title,

content,

comments {

content

}

}

}

You should get this result!

Now let’s add the username to those comments. Keep in mind that the following will create an N+1 situation for you. There are ways to help with this, and I may cover those in future blog posts, but it is beyond the scope of this article.

It’s simply a matter of adding the user type to our comment type:

module Types

class CommentType < Types::BaseObject

field :id, ID, null: false

field :content, String, null: true

# replace the user_id field with the following

field :user, Types::UserType, null: false

field :post_id, Integer, null: false

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

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

end

end

That’s it! Try the following query out now:

{

posts {

title,

content,

comments {

content,

user {

username

}

}

}

}

And here is the result:

Let’s get all the posts by a user. This one is easy too!

Change your query type file to the following:

module Types

class QueryType < Types::BaseObject

field :users, [Types::UserType], null: false field :posts, [Types::PostType], null: false do

argument :user_id, ID, required: false

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

argument :id, ID, required: true

end def post(id:)

Post.find(id)

end def posts(args)

if args

Post.where(args)

else

Post.all

end

end def users

User.all

end

end

end

If you submit the following query, you should see the posts by first_user:

query ($userId: ID) {

posts (userId: $userId) {

title,

content,

comments {

content,

user {

username

}

}

}

}

With variables set as:

{

"userId": 1

}

Good job, you did it! Happy Coding!