It’s a long road right there
I love building apps that scale. Both in terms of the codebase and the manpower.
As a developer focused on the two aspects of scalability, I decided to learn how to write software in a way that teamwork and software quality won’t be compromised.
I figured out good software is less tangled and works in smaller pieces. To be more productive therefore, I learnt to separate my business and application layer logic (APIs or backend) from the presenter layer code(UI or frontend).
I also advocate having a backend team separate from the frontend team. This will allow them to work independently and with their own standards and guiding principles, eg when it comes to testing and deployments.
Sorry for the banter. Lets now get to Rails and GraphQL!
The Ruby on Rails Architecture
We are not going to dive deep into this wide and broad topic. But to be able to build a good Ruby on Rails API, it is good to understand how it works from the basics.
Rails is built using the MVC architecture. MVC stands for Model, View and Controller.
A model maintains the relationship between an object/piece of data and where it is stored(database). It handles the object’s associations, validations, transactions and others. This is one of the major points of focus when building a scalable API. A model is what makes backend, backend.
A view deals with the presentation of data in a particular format — PDF, HTML, JSON, etc. But if you are building an API, the view is scrapped off. The frontend team will deal with this :)
A controller sits somewhat in the middle, in between the model and the view. On the other hand, it queries the model for data and on the other it organises that data into the format asked for by the corresponding view, before passing it on for rendering by the view.
Once again, since we are building an API, we do not have to worry about organising the data to fit the needs of the view, because here we are not touching the view part.
One other important part to understand about Rails is routing. A Rails router is a module that redirects incoming requests (via the browser URL) to the corresponding controller and actions.
Lots of quick and summarised Rails tips there. If most of these are new to you, I recommend reading Ruby on Rails: HTTP, MVC and Routing.
GraphQL
GraphQL is an open-source data query and manipulation language for APIs. From Wikipedia, it provides an efficient, powerful and flexible approach to developing web APIs. Flexible is the word here.
GraphQL allows clients (for our case the frontend team), to define the structure of the data required, and the backend will return exactly the same structure of the requested data.
Some of the benefits of developing your backend using GraphQL are:
- No more over-fetching or under-fetching of data. You get want you ask for
- Rapid product iterations on the backend and frontend
- Insightful analytics on the backend
- You get the benefits of a schema and type system
- It can be tied to any backend service. Meaning you can have a GraphQL + Rails app, a GraphQL + Go app, a GraphQl + … , you get the idea
Again, a lot has been said on GraphQL, so we are not going into all the detail there is. This was just to give you an overview of the system that will power our API. You can read more about it on HowToGraphQL
GraphQL on Rails
No, it's not a new fancy framework. GraphQL on Rails is what I like to use to refer to a Ruby on Rails application that uses GraphQL to implement it's API. Alright, let’s now see how the two, Rails and GraphQL, play together.
Just to reiterate, Ruby on Rails was built to work with the RESTful architectural pattern. Yes, REST is comparable with GraphQL.
Now, the two can work together. If you have an existing application built on REST, don’t throw it away! GraphQL is built in such a way that you can just add it to you project and continue building! To be specific, all you need is to install GraphQL and it’s dependencies and add a graphql
folder to your project! More on that in a bit.
If you are a long time RESTful dev, diving into GraphQL requires a little bit of a mindset change. You might be surprised not to find controller actions anymore, or even worse, finding out you just have two controller files in your entire project ¯_(ツ)_/¯
Don’t be surprised if you never touch your config/routes.rb
file ever again. It’s a different world out there.
What You Need To Know
As with almost every new and shiny tool, GraphQL comes with a new way of developing your APIs. Meaning a new approach to development, testing , team workflow and others.
Under this section, we are going to discuss three major knowledge points you need to be aware of as you shift. These are:
- Authentication
- Authorization
- Testing
Authentication
Authentication is the process of determining what user is making the current request, for example, accepting a username and password, or finding a User
in the database from a session.
In general, authentication is not addressed in GraphQL at all. Hmmm, you were not ready for that, were you?
Instead, your controller should get the current user based on the HTTP request (eg, an HTTP header or a cookie) and provide that information to the GraphQL query.
I’ll show you how to do it in a short while. Keep your cool.
Now, we all love gems. They take a whole load of work out of our chest. Unfortunately for our Rails + GraphQL API, you might not get a good authentication gem to work with. At least from my own point of view.
The popular authentication gem Devise doesn’t work well in API mode. Well, because it wasn’t meant to. It was made for full-stack Rails development. There are other gems such as devise_token_auth and simple_token_authentication (and others).
They work well and I don’t have a problem with them. But for me in particular, and it also being a GraphQL API (most of these gems are built to work on RESTful architectures), I didn’t have a good experience with them.
But let’s face it, all you need(mostly) is a registered User
object and an access_token
. So for me I followed these great tutorials and built a custom authentication system that generates JSON Web Tokens (JWT) for every new(sign up) and returning(sign in) users. I just tweaked them a little to work with the GraphQL controller (I’ll share the code so don’t worry).
Authorization
Authorization is the process of verifying that the current user has permission to do something or see something.
I must admit — one of the biggest challenges I had learning GraphQl + Rails was authorization. Many sources online just somehow didn’t help me get through this. The official GraphQL-Ruby docs do not very much show you how to do authorization, so yeah, I had a hard time figuring this out. And I hope my experience here will be of help to you.
Having used Pundit before, I wanted to try something like it. I tried it’s variants for GraphQL but they didn’t cut through. It was only until recently that Evil Martians released their own gem for handling authorization in GraphQL — Action Policy , which they’ve been using in production since 2018.
With action-policy, checking for a user’s permissions is as easy as authorize!user, to: :destroy?
I will write more on this at a following article, but for more, check the action policy docs. They’re pretty much well written.
Testing
You need to ensure the robustness, stability and compatibility of your application by writing good tests. Tests are what makes codebase scalability a breeze, you can add a feature without fearing that your changes will break the existing code. Good tests will always tell you when your code is going amiss.
From the GraphQL-Ruby docs, proper testing of a Rails and GraphQL API requires two kinds of tests:
- Structural tests: The kind that verify that the schema changes are backwards compatible. This way, you won’t break existing clients.
- Runtime tests: The kind that exercise the various parts of a GraphQL system, making sure that it returns the right data for the right client
You won’t be writing any feature specs (tests that exercise the view).
And apart from the controller tests you already have(if you do), you will most likely not write controller tests again.
You can read more about testing your GraphQL-Ruby project on the official docs page.
I have written a Rails + GraphQL application that I intend to use as a starter kit for all my new applications. It has both authentication and authorization set up, plus a few more user account management features. It’s called Nipishe, a Swahili word for ~ allow me pass :)
You can use it as a starting point.
I shall continue developing it and adding more user account management features.
I haven’t shared a lot of code on this article, but I will write sequel and more technical articles on how to authenticate and authorize your GraphQL on Rails app, with strict TDD, so stay tuned!
You can also let me know in the comments what I should include in my next write up!