00:00:11.380
Okay, please welcome Paul! Hello everyone, it's such an honor to be here in front of such a great audience.
00:00:22.750
I'm Paul, a web developer for five years. I have been a Ruby developer for five years and a former CTO. I am very interested in performance, automation, and related topics.
00:00:28.590
I really enjoy AI and machine learning in my off-time.
00:00:33.210
Today, I'm going to talk about my recent experience as a CTO and what I built there. I will outline my programs and explain why I transitioned from REST to GraphQL.
00:00:54.190
So, why are we building APIs? Building an API is about providing data to consumers, whether that's to a front-end application or a mobile application.
00:01:02.019
Rails gives us the API only Rails engine, which is straightforward to use. At that time, when I started the API for a large and ambitious project, I didn't really know the best approach to building an API.
00:01:15.570
I began with the JSON API standard. However, after a few weeks, things started to get messy. For example, when my front-end developer asked me for particular data in an endpoint, I found myself overwhelmed.
00:01:31.750
Initially, I set up numerous custom endpoints to accommodate these requests, but the structure became too complicated and tiresome. After about three months of building these challenging APIs, I decided to try a different approach.
00:02:11.410
I wanted to develop an API from scratch that I wouldn't need to revisit once it was done. That's when I discovered GraphQL, which was a revelation for me.
00:02:36.340
GraphQL allows you to have a single endpoint where consumers can query or mutate the data they need. This means you only need to manage one endpoint, which greatly simplifies everything.
00:02:41.860
With GraphQL, you also have the concept of subscriptions, which is akin to WebSockets. You can subscribe to a channel and perform various tasks through it.
00:03:04.450
We were quite entertained by GraphQL at the time, so I started exploring what had been done in Ruby for GraphQL. Thanks to Robert, the work on GraphQL was excellent.
00:03:28.390
However, I wanted to simplify the architecture further. I looked into domain-driven design principles and restructured some designs specifically for Rails.
00:03:54.880
I developed a gem that would clean and streamline the GraphQL architecture, effectively transforming a Rails API into a GraphQL API.
00:04:08.630
I think the best way to explain how this works is through an example. Let's create a simple API together.
00:04:17.220
For my first big conference in English, I wanted to gather feedback, so I'll create an API that allows for that. We will have speakers, spectators, comments, and categories for talks.
00:04:25.350
This will be a simple API that allows users to create speakers, spectators, comments, and tags, as well as modify and destroy them as needed.
00:04:42.010
Next, I will set up an application using PostgreSQL because it handles UUIDs well and works neatly with front ends. I will add the Gemma GraphQL and GraphQL Rails API to my application.
00:05:14.390
After that, I created the database and designed my data model. For example, a speaker has a name and many talks, which means you can define relationships between the entities.
00:05:41.640
For instance, a talk belongs to a speaker while a spectator has a body and belongs to both a talk and a speaker. I described the model, and from there, I generated my GraphQL API.
00:06:09.160
This made it possible to create backend logic for generating the necessary migrations, models, and GraphQL types and mutations automatically.
00:06:36.290
Whenever I add a speaker who has many talks, the system automatically includes a speaker ID in the talk model and sets everything up.
00:07:04.450
Now, let me show you the results in code. As you can see, I am working with GraphQL, and I only have one controller, which is the GraphQL controller. In my routes, I only need one route that relates to the GraphQL method.
00:07:40.560
This route executes the GraphQL query passed as a parameter and handles user authentication. You can authenticate your user however you want and pass it into GraphQL.
00:08:19.320
The structure has also been designed to correspond with domain-driven principles. For example, if I take a command, its type automatically includes spectator ID, talk ID, body, timestamps, and IDs.
00:09:01.740
In addition, the mutation creates, destroys, updates, and has input types, which defines the data sent to create or update commands.
00:09:26.970
In the service layer, this is where you manage your business logic. For instance, if you want to change how commands are created, you simply redefine the creation method here, and it updates automatically.
00:09:50.460
My domains and services are organized so that you can test the logic easily. I have incorporated visibility filters into my gem, allowing filtering of commands.
00:10:20.940
For example, if I want to filter commands based on the authenticated user, I can easily do that so that they only see their own commands.
00:10:47.010
The advanced querying functionality is another powerful aspect of GraphQL, including querying for specific fields while ensuring optimal database queries.
00:11:29.820
For instance, when creating commands, you simply invoke a mutation like 'create a command' or 'create a spectator'. It's straightforward.
00:12:11.520
To demonstrate this, I have deployed the application on Heroku, and you can access it via the provided URL. Feel free to try it out and have fun with it.
00:12:34.660
You can post comments, and I will check them. Thank you!
00:12:59.050
Thank you so much!
00:13:05.960
Does anyone have any comments or questions?
00:13:18.230
Yes, thank you very much for your talk! I have been looking for an opportunity to use GraphQL for a while, but I often find myself unable to destroy my existing JSON API and start from scratch.
00:13:50.400
What would you advise in this scenario? It appears that the barrier to entry for GraphQL, in terms of the amount of code required to implement it, is quite high.
00:14:13.750
It can be high, but you can add the GraphQL layer to your existing Rails application easily. Just add it and introduce your types iteratively.
00:14:41.080
You don't have to overhaul your entire API at once; instead, do it resource by resource. Your front-end developers will appreciate using the new GraphQL resources.
00:15:28.830
There is another question? Yes, what happens when a request comes in for a field that no longer exists? Do you have an unknown contract to retain or will it throw an error?
00:15:55.640
For GraphQL, you have access to your schema and can ask for the possible queries. The GraphQL documentation explorer allows you to see what you can query.
00:16:40.230
If you try to query a misspelled field, it will inform you that the field does not exist. That adds a layer of robustness to the querying process.
00:17:25.250
Thank you. Are there any other questions?
00:17:47.940
Hi, thank you for the talk. I wonder how you handle the increased responsibilities of the front-end with this approach dealing with API.
00:18:29.370
That's not entirely true because you can enhance your API however you want. It's similar to a REST API; developers find it easy to adapt. Frameworks like Apollo or Relay help in managing this complexity.
00:19:20.370
The front-end teams I worked with were eager to add logic in the front end when it's appropriate. All backend logic remains intact.
00:19:55.670
Hi, thank you for the talk. How do you deal with filtering data at the request level? For instance, if I want to get talks that include 'Ruby' in the title?
00:20:32.900
You can easily add arguments to your queries to filter data. You could append, for instance, a search field in your query to only retrieve talks with 'Ruby' in the title.
00:21:14.020
Does that clarify how you specify it on the front-end?
00:21:32.820
You can structure the arguments neatly in your GraphQL queries to enforce filtering based on user input; this approach is both flexible and efficient.
00:22:14.720
Thank you for pointing that out. Any other questions?
00:22:40.210
How are validation errors returned in an update request?
00:23:15.800
Validations are set up, so when a required field is missing, the error gets returned in an array format, which provides feedback on what went wrong.
00:23:49.030
If you attempt to create a spectator without a name, the input type validation will block that and return an appropriate error message.
00:24:30.890
I want to better understand the reasoning behind your switch from JSON API to GraphQL, especially considering the specifications.
00:25:35.570
The JSON API specification does allow for specific fields to be requested, yet the limitations regarding deeply nested relationships and filtering are why I favored the flexibility that GraphQL offers.
00:26:05.170
In conclusion, thank you for your attention, and I appreciate the questions you've shared.