Better Rails APIs with RABL

Web development is changing. It seems that every day I come across another Javascript framework. More than ever, I am spending time not writing partials or views––but defining APIs that my front-end code can use. It does not seem that Rails 'to_json' is the ideal solution for defining these API's that are becoming more complex.

How we have always done it

One thing that has always bothered me about the way we have always done it: JSON is becoming the new view in a world where server calls are becoming less frequent.

Typical rails controller

1 2 3 4 5 6 7 8 9 10 11
class RailsController < ApplicationController
respond_to :json
 
def index
@students = Student.all
respond_with(@students) do |format|
format.json { render :json => @students.to_json(:only => [:firstname, :lastname, :email, :phonenum])}
end
end
 
end
view raw rails_controller.rb hosted with ❤ by GitHub

JSON Result

1 2 3 4 5 6 7 8 9 10 11 12 13 14
[
{
"email": "info@heysparkbox.com",
"firstname": "Drew",
"lastname": "Clemens",
"phonenum": "937-401-9501"
},
{
"email": "info@heysparkbox.com",
"firstname": "Andy",
"lastname": "Rossi",
"phonenum": "937-401-9501"
}
]
view raw rails_json.js hosted with ❤ by GitHub

This is a simple example that does not have any includes or methods that need to be added from the model. This could quickly become a very large block of code in the controller. This does not feel like controller code to me; I have always wanted to push this code to the view. Until recently, I only ever had a few places where this was an issue so I ignored it. More and more it seems like our JSON API's are growing. In some cases most of the view rendering is taking place in JavaScript. I want and need more control over my JSON, as it is becoming the major contract in my code. This way seems to work well if your API reflects what is in your model. While this may be easy, if things had to change on the back-end I could not easily hide it from the client (my front-end code). This creates a coupling that makes me squeamish.

A new way

RABL (Ruby API Builder Language) provides a way to use a templating system for generating JSON or XML in your view. RABL is a simple DSL that allows you to define your JSON responses in an easy, clean way. It is easy to setup with Rails 2.X, Rails 3, and Rails 3.X.

Using RABL the above becomes:

New rails controller with RABL

1 2 3 4 5 6 7 8
class RablController < ApplicationController
respond_to :json
def index
@students = Student.all
end
 
end
view raw rabl_controller.rb hosted with ❤ by GitHub

New RABL view file

1 2 3
object @students
 
attributes :firstname, :lastname, :email, :phonenum
view raw index.rabl hosted with ❤ by GitHub

JSON Result

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
[
{
"student": {
"firstname": "Drew",
"lastname": "Clemens",
"email": "info@heysparkbox.com",
"phonenum": "937-401-9501"
}
},
{
"student": {
"firstname": "Andy",
"lastname": "Rossi",
"email": "info@heysparkbox.com",
"phonenum": "937-401-9501"
}
}
]
view raw rabl_json.js hosted with ❤ by GitHub

At the end of the day I think that RABL provides a better way to define my APIs. Please note that my examples above are overly simple. This was done to show the ideas I am talking about. Please check out RABL for yourself to see if you think it's a better solution.

Other RABL resources

RABL on GitHub - https://github.com/nesquena/rabl

'If you’re using to_json, you’re doing it wrong' - http://engineering.gomiso.com/2011/05/16/if-youre-using-to_json-youre-doing-it-wrong/