GraphQL with Ruby On Rails: Queries in Multiple Files

GraphQL with Ruby On Rails: Queries in Multiple Files

In the last episode, we added RSpecs tests for GraphQL mutations. If you need some more insight about the topic you can check the article here. Today we are going to add specs (again, we will focus only on the happy paths) for GraphQL queries. But there is one thing about the current implementation of the queries that I don’t like. We have everything defined in one file: app/graphql/types/query_type.rb

You can imagine that this file will grow over time. I want to show you how to divide the logic into many smaller pieces.

The first step of every refactoring

It is hard to do refactoring without proper specs. So we are going to add specs first. But to make the article a little shorter and easier to comprehend, we will embrace the approach we put a great emphasis on in our company. We will do a test-driven development. That means that we will write the final specs. So instead of adding specs to our previous implementation, we will add specs for the future implementation where every query is defined in a separate file.

We would like to have a structure where all queries are inside app/graphql/queries/ folder. Therefore our specs will end up in specs/graphql/queries/ directory.

specs/graphql/queries/author_spec.rb

specs/graphql/queries/authors_spec.rb

specs/graphql/queries/bookspec.rb and specs/graphql/queries/booksspec.rb are almost the same so I’am not going to paste the code in here. Instead, you can check the files on gist if you like: book_spec.rb and books_spec.rb

As you can see our new specs look really similar to those we wrote for mutations. We have a query method that we use for building GraphQL query and we check if the result of the query meets our expectations.

Dividing queries into separate files

Now when all needed specs are in place we can finally do the refactoring. I am not going to show a proper TDD in this article because it will require those actions over and over again: run spec, see the error, fix the error, run spec again to see another error, fix that error etc. It will be hard to follow so I’m going to present the final solution and explain the idea behind it.

We want to have a similar structure to what we have in mutations but it is not supported and we need to look for alternatives. The one we usually use for splitting queries is Resolvers.

Disclaimer: it is not always recommended. Please check the documentation for more information.

As I mentioned many times, we want our query_type.rb to work similar to mutation_type.rb it means that new version of app/graphql/types/query_type.rb should look like this:

We removed all the logic we had. Instead, we define what query is available and the resolver for that query (a place when we can find it).

If we are going to follow the mutations’ way of doing things we need an additional file: app/graphql/queries/base_query.rb

It is empty for now, but in the future episodes, we will use it for some cool things.

We can finally see the implementation of our new queries:

app/graphql/queries/author.rb

app/graphql/queries/authors.rb

app/graphql/queries/book.rb

app/graphql/queries/books.rb

The code of each query is moved from the query_type.rb without any changes. The magic that makes it possible is the inheritance from Queries::BaseQuery which inherits from GraphQL::Schema::Resolver. That is it.

Summary

At this point we have all the endpoints tested out and we (almost) have a structure that is easy to build on. In the future episodes, we will discuss things like pagination, authentication, authorization and many more.

Related articles