Let’s forget painful API documentation

How to document your Rest Api On Rails with Rswag

Grégoire Marnotte
Wolox
Published in
8 min readJan 29, 2019

--

This is going to be a complete guide about how to document a Rest Api and why it is important to document an API. Also, we will present a gem, Rswag, which will ease the amount of work needed to generate Swagger documentation, with a complete tutorial to set it in a Ruby On Rails API.

Introduction

Developing an API is about more than just coding, and with the number of endpoints and the complexity of the logic increasing the role of managing, communicating and planning is becoming more important and taking more time. In order to have efficient communication between the team developing the API and the developers who use it, documentation is the key to success.

However, maintaining clear documentation could be a challenge. It is usually not the developers’ favorite part and it’s difficult to assign a person to just focus on documentation maintenance.

Based on these observations, this article has a solution: generate automatic documentation based on integral testing. This is a genius idea: any change in the documentation will be detected and the developer can fix it. When they push a new endpoint for a code review, the owners are able to verify the creation of the documentation before accepting the merge. In this manner the documentation remains up to date.

In order to do that we use the gem Rswag on Rest API craft with Ruby On Rails. In the following paragraphs, we will present why you should or shouldn’t use this gem and provide a tutorial trying to go deeper than the README of the gem.

Let’s start with a classic pros and cons

Generalities

If you started reading this paragraph, surely you do need not to be convinced of the importance of complete and well maintained API documentation. But just in case you aren’t convinced yet, you can consult this article to finish convincing you.

Before, presenting the Rsawg gem let me provide you with some background information. There are a lot of options to build documentation, such as Apiary, or the documentation tool from POSTMAN... The one we are exploring here is Swagger, a tool to Design, Build, Document, Test and Standardize APIs. Here we will use it mainly to generate documentation and expose the API across it’s UI.

We will use Swagger across the gem Rswag. Let’s take a look at the good and the bad of the gem before starting the tutorial.

Pros

  • Documentation is validated by an integration test: In order to generate the documentation we need to run a valid test, that’s why devs must keep the documentation up to date;
  • Continuous maintenance of documentation: during the code review process (pull or merge request) it’s possible to verify the addition of the valid integration test to generate documentation, and have up to date documentation;
  • Assign a documenting task to each dev: each dev from the API has the duty to maintain his/her modifications of the code to reflect on the documentation;
  • It’s automatic: only the integration test needs to be generated, the rest is the job of the gem;
  • UI 3.0 from Swagger;

Cons

  • Adds time on endpoint crafting: every time a new endpoint is a craft or modification, the dev must take time to update the documentation;
  • Adds time for the reviewer: the reviewer needs to check more lines with counting integration tests;
  • Run on Swagger 2.0 Open API Specification: schema option not always all available, if you need to document an API built on micro services it’s more difficult… (I post an issue on the gem, let’s see what’s happening.);
  • One body response by HTTP status code: sometimes you have multiple responses to a document on the same HTTP status code, and depending on the header, Swagger does not allow this.

Use it in your API

Setting up an example

Let’s imagine we are building an API to manage wine, the API is very basic and contains:

  • A model of wine:
  1. Name: string;
  2. Grape variety: an array of string;
  3. Type: enum [white, red];
  • A CRUD accessible by an admin for wine model;
  • An index to consult all wines;

We will build all the following in this example.

Install the gem

Step 1: Install it

On your current application or on a new application, add these lines to your Gemfile:

Install the gem and use task from them to generate files needed:

Step 2: configure it

Before creating any documentation let’s take a look at the configuration files. In /config/initializer/rswag-api.rb the path where Json configuration files will be created is defined. It should be equal to this, but it can be adapted to fit your requirement:

We will resume with the routes config. These 2 lines should be added and [api] should be replaced by the name of your choice. The UI route is the one that will be used to access to the documentation on the browser:

Now the initializer of the swagger UI:

There are 2 data to consider:

  1. where the gem should look for the JSON configuration file in your project. The first part of the path depends on the routing you use in routes.rb for API
  2. the name which will show up on the HTML:
Expend selector on Swagger UI navigation bar

In order to allow an auto-generating body response in this example, we will need to add these lines to application.rb:

Lastly, maybe you have some logic to protect you from rack attack. An integration test quickly prevents rack attack from sending a 429. Change its request limits:

Step 3: Hide files for pull request (optional)

The JSON configuration files are auto-generated and will change each time we regenerate the documentation. We do not want to show these changes on a pull request, so we will add this to our project:

Create an integration test for documentation

Step 1: set up the Swagger Helper

We will edit the file (swagger_helper.rb) generated by the task that we ran before, which helped us define the structure of our documentation and our general settings. Two configurations are used here:

  1. swagger_root: is the path where the gem will generate JSON configuration file and should be the same as the one in the initializer for rswag-api;
  2. swagger_docs: is the general configuration of the documentation. Here, we need to organize the different endpoints we have, one for the admin side and one for the average user. For example:
  • swagger_admin_doc: endpoints for an admin;
  • api/swagger_doc.json: for usual user

Now we will be going deeper into some options used in swagger_docs config:

  • First of all, you should define the path where the JSON configuration file will be generated;
  • swagger: This is the version of Swagger (OpenAPI) Spec. used, there is no version higher than 2.0 maintained by the actual gem :/ ;
  • info: some generic information on the documentation (title: will appear on the top of the doc; version: will appear near the title);
  • path: we will let this option to {} to have the complete path on the endpoint;
  • securityDefinitions: is used to define the way we deal with the authentication. ( If you use microservices and Bearer Token, this will not be supported by swagger 2.0).

Step 2: Let’s create a shared piece of test

Each time we want to generate documentation we need to add the line run_test! on the code. Also to enable the gem to automatically generate a response body example we need to add some lines. So what’s better than a share_context for that:

(Do not forget to add code in your rails helper to require files you have in your support directory)

Step 3: Document your endpoints

Each endpoint needs specific data, and the structure must be adapted for each one. But here we will try to give the general structure for each type (GET, POST, PATCH, DELETE), so we have common knowledge about how to build the integration test. And that’s perfect because in our CRUD we have this type of endpoint.

Also, gem allows us to use all method from rspec.

Moreover, we call this integration test because when rspec is run, this integration test will also be run and should not fail…This will allow us to better maintain the documentation and be sure we are creating the necessary documentation.

The idea is to create an integration file for each controller, for example:

  • app/controllers/api/wines_controller.rb -> spec/integration/api/wines_spec.rb
  • app/controllers/api/admin/wines_controller.rb -> spec/integration/api/admin/wines_spec.rb

Also, each file will contain:

Important things to notice:

  • swagger_doc: the path to the JSON file will contain the configuration to generate documentation;
  • TAGS_[controller_name]: allows the regrouping of the controller’s endpoints in the same group.
The result expected should be this one, with Wines controller

GET (index)

We will start with the simplest:

There is nothing special to explain about this structure, it is simple and there are only a few lines. We advise you to note the author in the description, this allows the front team to know who to talk to in case they have concerns.

Also notice we are using our shared_context, here.

Maybe you want to add query params (after the path), for that add:

The let could be defined in or out of the response.

GET (show)

Let’s try a more complicated one:

What to notice there:

  1. Path containing the {id} params;
  2. Same tags as before are used to regroup the endpoints;
  3. You can add a description;
  4. The id params are defined with its specs in the parameter;
  5. Two responses are documented (200 y 404);

POST / PUT / PATCH

Here we only highlight a POST, because put should have an equivalent structure.

Things to highlight in this example:

  1. An entry consumes was added;
  2. Body params must have had a complete schema, with types, properties, enums… In the example, you will be able to produce anything you want, but if it lacks something consult this link.
  3. All possible response codes should be documented;
  4. The include_context is still used here to automatically generate the example body response;

Note: If you have a complex body and want to see an example directly you can do this:

DELETE

The only thing I need to mention here is the response in the controller is a simple head: :ok. So the body response is nil. As a consequence, we do not use the share_context but only a simple run_test!. It’s also possible to adapt the shared_context to handle this case.

GET (index) out of admin

We also have an endpoint from the admin side. Let document it:

The key is to change the swagger_doc variable and the variable name TAGS_WINES. And the document will be generated in the right place.

Generate the documentation

  1. First of all, verify your integration test passed;
  2. Generate the documentation;
  3. Run your server.

Access to the documentation:

http://localhost:3000/[service]-docs/

Docuementing an API and keeping it updated is essential. It is hard work and can be painful. Luckily there are tools to reduce the amount of work and Rswag is a quite good solution even if it has some limitations.

--

--