Welcome to the sixth chapter of the API-only ruby on rails course. This time, we will improve the renderer module, which we introduced in the previous chapter. If you didn’t read the previous sections yet, you can check the content list from the overview page.
Last time we have built the following renderer module and used it in the users controller.
This module provides a single place where we can modify the payload structure for all API endpoints. As a first step of the improvement, let’s talk about the payload structure we want to build. For the API responses that expose data, I would suggest using the following format with the resource and its metadata information.
data: will provide resource information. If it’s not a single resource, we will have an array instead of an object as a value of the data key.
meta: will provide metadata information about the resource. It will give the resource name as well as the total number of returned objects.
Also, for the API responses that expose errors, we will use a structure that looks like the following.
We provided the field names and corresponding error explanations as an array. (One field might have more than one error.) I don’t think having the metadata information gives us so much advantage for the errors, so I excluded it from the error payloads.
Improve renderer module
Let’s start improving the render_object method of the renderer module to have the structure we mentioned.
Instead of getting status as a second parameter, we got all keyword arguments after resource argument as options since we want to pass all of them to the active model’s serialization process. Those options might include serializer, root key, etc. in addition to the status.
After getting options, we merged the resource with the JSON key and added data as a root key. Status logic is the same as previous behavior. If the status code is provided, we will use it. Otherwise, it’s going to be 200 (ok) as the default.
Let’s run the renderer module specs to see if everything still works as expected.
We have one error because inside the renderer module test, we were expecting to get data with dummy root key, but with the last improvement, we changed it to the data key. So we need to replace it with the data key.
We can also create another helper method in spec/support/json_helpers.rb to get the data field of response body directly.
And we will use load_body_data method for the renderer tests. It’s also better to name resource_fields as data_fields from now on.
And now, let’s rerun the tests.
It’s passing again. We also have to modify api/v1/users_spec.rb file because we passed status as a second argument previously, but we need to convert it to the keyword argument to get it through the options we defined in the renderer module.
We will also modify spec/requests/api/v1/users_spec.rb file because creates a new user case has the user root key that is supposed to be data with new changes. And also, it’s better to name it as expected_data rather than expected_body since it reflects the data part of the response body rather than the whole response body. (This is an unnoticed point from the previous chapter, I want to correct it here.)
Let’s run the api/v1/users_spec.rb to see whether it’s working or not.
Perfect! Let’s move to the next topic.
Introduce metadata information
We added data as a root key for all API actions that are going to use the render_object method. But we also want to include metadata information of the resource. Now, we can add the assign_metadata method to the renderer module.
Now, we need to modify the renderer module test to cover the metadata part of the response. Before doing that, we can add load_body_meta method to the spec/support/json_helpers.rb file as we did similar to the load_body_data.
Now we can adjust renderer test to cover metadata information.
With the last changes, we can run the renderer module tests.
Yay! We have completed the improvements of the render_object method.
Add errors as a root key
One last improvement to do is adding the errors root field for the render_errors method. Let’s modify the renderer module.
We will also add errors root key to the renderer test.
Similar to the load_body_data and load_body_meta we can create another helper method for the errors in spec/support/json_helpers.rb.
After adding load_body_errors method as descripted, let’s refactor the test by using load_body_errors method.
We also need to do same modification for the spec/requests/api/v1/users_spec.rb file.
We completed the enhancement of the payload abstraction. Now, we can run all tests to see everything is still working.
Summary
In this chapter, we structured the API response payloads by improving the renderer module. With the improment, API payloads will expose data and meta information of the resource. In the next chapter, we will start working on swagger integration for the API documentation. 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.