APIs With Rails:render :json => The_simple_way

Lately my work at Fancy Pixel has focused on the backend of a product we’re about to launch and for which we decided to build a JSON API-only server. These APIs can be consumed from third party clients/services but are also used by our frontend. In this short report I’d like to share with you the simple solution that we’re using for the JSON generation and that in my humble opinion can be a quick and easy alternative to most commonly used systems like Jbuilder or ActiveModel::Serializers.

Rails, one of my favourite work buddies that I happened to use several times on projects that included the development of APIs. Due to personal curiosity, during the years I had the opportunity to try several solutions for JSON generation and I have to say that sometimes I found some difficulties with certain tecnologies: great for the majority of their functionalities sometimes they may force you to take weird paths to achieve the desired result. To be honest, the main reason for this continuative experimentation is probably the constant search for the top balance between comfort/ease of use/development-speed and performances and after all this test and try I arrived to the current solution, that probably is not something new, but that in my opinion can give somebody an alternative idea combining together great flexibility and bare metal performances.

To cut a long story short…

I don’t want to dwell with epic tales or “disquisitions about the gender of the Angels” so I built a trivial demo app that you can find on our GitHub account, to show you what I’m talking about.

For the purposes of this article I decided to use rails-api (if you don’t already know it I reccomend you to give it a try) instead of standard Rails, for the simple fact that this is what we’re using right now in the project I mentioned at the beginning of this post. Obviously the same concepts apply identically to vanilla Rails.
Let’s open together the code and take a rapid look at it: as you can see these few lines of source do nothing but respond to three routes and if you take a look at config/routes.rb you’ll find something like:

As you can see I’ve set json as the default format and I defined a namespace in such a way to replicate a typical process of APIs versioning.
Let’s jump to the only existing controller (comparison_controller) where we find the implementation of the actions called from the routes. Each of these actions does exactly the same: load a bunch of records from the DB and render it as JSON, but each one does the rendering in its own way i.e. using respectively jbuilder, ActiveModel::Serializers and “my solution” that I’m going to call “simple”… what a fancy name uh?

We’re not going to focus on the first two systems, because chances are that you master those tecnologies better than me already and, also, there is nothing out of standard in my implementations, but instead we’re jumping feet together to the simple action. Like the competitors, it does nothing more than render some JSON, but this time the serialize_awesome_stuffs helper method is called. This method is defined in the V1::SimpleAwesomeStuffSerializer module that is included by the controller. You can find the module under app/serializers/v1 and if you’re going to open the file you’ll notice that it’s just a plain Ruby module defining methods.

Both the methods do nothing more that returning an Hash defining key-values couples that we’re willing to return as JSON. In particular serialize_awesome_stuffs creates an Array of Hash and internally, just for DRYing things up a bit, calls serialize_awesome_stuff (singular). Maybe the overall naming is not the best in the world, uh? Bonus point: defining the method’s parameter awesome_stuffs = @awesome_stuffs allows us to make our code lighter and more readable, because if we remained adherent to conventional variable naming, probably our controller is defining something like @awesome_stuff (and as a matter of fact, we did) that is directly visible and usable by our module. If we’re going to have a bout of creativity and want to use our personal variables names, we won’t have any sort of problem.

Now that everything is prepared, let’s follow some of the steps we’d usually do during an API creation. Let’s create a UserController through which return to the client also user’s associated awesome records™.
Create users_controller.rb` underapp/controllers/v1/and addindex“` action:

As you can see I already added some stuff that we’ll need in short, that is the V1::UsersSerializer module. If you haven’t already, notice the scoping (V1) of our serializers: in doing so we can follow the evolution of our API’s versions with no hassles, possibly going to redefine the behavior of only serializers that may change.
Do not forget to add new routes:

What you’ve seen so far is a simple example of what it’s possibile to do with the tools we already have at hand and mainly wants to be an idea for those wo are constantly looking for the best performances and simplicity.

We reached the end and I hope I have not bored you too much, but if you got to this point, I probably didn’t :)
What you have seen today may or may not be liked, but I personally find it a surely performant system that offers pure modularity, extensibility and code reuse.