Let’s say we have a Rails app that uploads images using carrierwave. We want to extend this functionality to let a mobile app upload images as well. The only constants we know are that the photos should be sent to our Rails app through a RESTful JSON API, and that the images are strings encoded in base64.
We need a place to store the images. We could use a generator to create a Post table that has an image column which stores strings.
With our generated model, we attach a base64 image uploader which will allow us to attach an object in the fields of our database. The code still looks like an ordinary carrierwave implementation – but with a really small difference. Instead of having mount_uploader in the model, we would add mount_base64_uploader instead.
Now that can save a base64 image, we now have to create an API endpoint that our mobile app can call so they can post images.
Creating the JSON API Endpoint
Although there is a lot more to explore in jsonapi-resources, I will only touch on just a few of its really cool features. I believe this gem deserves its own blog post on how much benefit it provides with just a few lines of code.
Now let’s create a jsonapi-resources controller and resource with generators that the gem provides.
Although the ApplicationController that we have written inherits from the jsonapi-resources controller, this can also be a normal controller that includes a ActsAsResourceController.
In the routes, we are using the jsonapi_resources method. This gives us a lot of useful endpoints. For the sake of this example, let’s just focus on a posting endpoint and add only: [:create]. Thus giving:
This is actually all we need to post a base64 image through an API. From here we can use Postman:
Stretch Goal: Testing & Documentation
rspec api documentation
It is important to test and document API implementations. With rspec_api_documentation, we can do both at the same time. In my opinion, the best part of using this gem is that it does not generate the documentation for a failed example. It runs all the acceptance test, and if it passes, it generates the documentation. Once the documentation is re-generated, all the documentation is removed and generates a new one. Also, example documentation can be skipped with the document: false option.
First we need to tell rspec_api_documentation that we are going to be formatting the body to a JSON response by adding this helper:
Now that is all set up, we can start writing our test.
To set up our test, we would first have to include rspec_api_documentation dsl. This gives us wrappers to have headers to our requests and setting HTTP verbs as context. We also use resource instead of describe to define what we are testing.
Below I have added a method that will be passed in a request method in my “example” (“example” in an acceptance test is analogous to an it block). A header method takes in 2 arguments: the header field name as a string and the header value.
Now, let’s examine what goes in the test. In rspec we normally use describe or context. In an rspec_api_documentation test, we use the http verb, followed by the path that we want to test. It also takes in a block that contains a do_request method. This method can take in an argument. In a GET request, it does not need an argument, but for our case, the POST request takes in a hash as an argument.
Run the test and generate the docs with:
The docs are available at http://localhost:3000/docs/api and with the help of apitome this would look really cool! In essence, apitome is a wrapper for rspec_api_documentation to enhance the generated documentation.
Creating an API endpoint is never complete without a good proper documentation. With this API bootstrap combo for Rails, it makes mobile image upload feature easier. See how awesome this combo is with my toy app! Follow this link to go to the website, and this link to go to the api documentation