02 August 2020
Welcome to the seventh chapter of the API-only ruby on rails course. This time, we will implement the first part of the swagger documentation for the API endpoints. If you didn’t read the previous sections yet, you can check the content list from the overview page.
I assume most of you already know or used swagger for the API documentation and testing, but let me quickly explain why we want to use swagger. Swagger is a specification (recently called OpenAPI specification) that allows you to describe available API endpoints and operations on each endpoint using a JSON or YAML file. By using the swagger file with swagger UI, we can interactively document and test API endpoints. You can check the example swagger file here. You can also see how this file looks like using together with swagger UI here. As you can see, swagger UI allows client developers to see the living example of the API endpoints. They can see all the details of requests and responses for each endpoint.
For the swagger integration with rails applications, there are some different approaches. Some of them are using tests to document API. Using test files to generate API documentation feels like mixing two big responsibility into the one. Let’s say you have a strict deadline, which you might think about not maintaining the documentation for a while but want to have tests anyway. Using both of them in the same place will make it challenging to deal with that situation. You might think like “doing one of them is already covers both of them” but actually, you need to have more extended specs than the usual in case you want to generate swagger documentation from the specs.
The other approach is auto-generating the swagger documentation. Even though those libraries are announced as auto-generated, you still need to work on them. The nature of the ruby (a dynamically typed language) doesn’t allow you to understand the types of request parameters or response payload fields. Or if you have a rescue
block for all API endpoints for the 404 (not found)
response, you need to document it anyway manually. So it’s half automation, half manual maintenance work.
Another approach is writing the documentation explicitly, which we will use along with the course. It will add maintenance costs to the development process, but it’s the easiest and pretty straightforward option.
I would like to use swagger-blocks gem to integrate swagger since it’s aligned with the third option that we discussed. The gem has a DSL that allows us to write API documentation manually. Also, we will create a controller which generates and exposes a JSON file from the code that we write by using swagger-blocks
DSL. (After we have a swagger JSON, we will integrate swagger-ui to show them interactively in the next chapters.)
Let’s start by adding swagger-blocks
gem to the Gemfile
and then run bundle install
command.
Now we will follow the instructions from the documentation of the swagger-blocks
gem. Let’s start by creating app/controllers/apidocs_controller.rb
file.
Here, we defined the general information of the API documentation with specifying version
, title
, host
, basePath
, etc. We will include other classes that describe the endpoints and resources to the SWAGGERED_CLASSES
, but we can ignore it for now. With the index
action, we’re building the JSON file using all classes specified. We don’t have any other class which uses swagger-blocks
than ApidocsController
at the moment.
And now, we need to add apidocs#index
action to the routes.
If you go to the http://localhost:3000/apidocs address in your browser, it will render the swagger file generated, but we have only the general information of the API for now. Let’s add the necessary documentation classes for the user creation endpoint.
It’s better to have a namespace for the classes we would like to use with swagger. Therefore, let’s create a swagger
folder in the app/controllers
folder. Then, inside of the swagger
folder create controllers
and models
folders. Controllers will reflect the classes that we use to document API endpoints, while models will reflect the request and response payloads.
Let’s start by creating app/controllers/swagger/models/user_input.rb
. It’s the file we define the request payload of the user creation endpoint.
Here, we basically defined the request payload fields for the POST api/v1/users
endpoint. After that we need to add this file to the SWAGGERED_CLASSES
inside the apidocs_controller.rb
file.
And now we can document the user creation API endpoint. To do this, let’s create the app/controllers/swagger/controllers/users_controller.rb
file.
We added the request information for the POST
request of the user resource. We then defined the request details by specifying the UserInput
class that we described above as a request payload.
And again let’s add it to the ApidocsController
, as we similarly did with the UserInput
.
And if you go to the http://localhost:3000/apidocs you will see the generated JSON with the recent documentation we added with classes. For now, we don’t have any user interface to see what it looks like, but you can copy the generated file into the swagger editor and check how it works with swagger-ui. (To do that, you also need to adjust CORS settings, which we didn’t in the course yet!)
In this chapter, we started to build API documentation by using swagger
. We don’t have a user interface yet, but we have an action that generates the swagger file. In the next chapters, we will add responses to the API documentation along with the status codes and payloads. We will also integrate swagger UI into the project. You can find the source code of bookmarker application on github. You can also find the previous chapter here.
Thank you for reading! If you want to be notified when I publish a new chapter, you can follow me on twitter.