If you look at the gemfile for a Rails 3.2 application you’ll see a see a gem mentioned in the comments that wasn’t there in earlier versions called JBuilder.

/Gemfile

# To use Jbuilder templates for JSON# gem 'jbuilder'

JBuilder is a template engine for rendering a JSON response. It was created recently by David Heinemeier Hannson but instead of including it in Rails 3.2 he decided to release it as a separate gem. This approach means that it can also be used with earlier versions of Rails. JBuilder provides a nice DSL for generating JSON similar to XML Builder and we’ll show you how to use it in this episode.

Adding JSON Responses to an Application

To demonstrate JBuilder we’ll use a simple blogging application. This app has many articles and we’d like to add a JSON representation for each article that we can fetch by appending .json to the article’s URL. If we try this now we’ll see an error message as we haven’t yet added this feature.

We could add this without using JBuilder by adding a respond_to block to the ArticlesController’s show action.

When we reload the page now we’ll see the JSON representation of the article.

Customizing The Response

The JSON returned includes all of the article’s attributes but what if we want to customize it? This is where things can start to get ugly. We can call as_json on the article and customize what’s returned. Let’s say that we want the id, name and content fields from the article along with its author and the same three fields from the article’s comments.

We can try this by reloading the page again. When we do we see the customized JSON response including the associated Author and Comment records.

Using JBuilder

This works, but the code we’ve used isn’t very pretty. We could override as_json in the model but this wouldn’t be much prettier. This is where JBuilder comes in. To install it we uncomment the relevant line in the gemfile and run bundle.

/Gemfile

# To use Jbuilder templates for JSON
gem 'jbuilder'

Back in the controller we can remove the respond_to call and revert to the default behaviour which is to look for a template for the requested format.

/app/controllers/articles_controller.rb

defshow@article = Article.find(params[:id])
end

Next we’ll create a JSON template in the /app/views/articles directory. In it we can use Ruby code to define the JSON output. We have access to a json object that we can define attributes on like this:

/app/views/articles/show.json.jbuilder

json.id @article.id
json.name @article.name

We’ll need to restart the server after we’ve installed the gem but once we have and we reload the page again we’ll see our custom output.

It can be a pain to have to list out each attribute separately like this. Instead we can call extract! on the JSON object and pass in the object and a list of the methods or attributes we want to call against it.

/app/views/articles/show.json.jbuilder

json.extract! @article, :id, :name, :published_at

There’s an alternative syntax for this as well.

/app/views/articles/show.json.jbuilder

json.(@article, :id, :name, :published_at)

This works only in Ruby 1.9 as it calls call on the object in the background which will call the extract! method as before. One nice thing about rendering JSON in a view template like this is that we have access to all of the helper methods. This is especially useful for rendering URLs. If we want to include the edit article URL in the JSON but only if the current user is an admin. We have access to the current_user method too if the authentication solution we’re using offers this as a helper method.

If we need to use the block syntax with this approach it’s a little different because we have an array of comments and we need to iterate through each element of the array. What we do is pass in the json and comment objects into the block which gives us access to it and we can do what we like with it in there.

Partials

If we find ourselves filling up the comment block with a lot of detail and we need to duplicate this functionality elsewhere we can use a partial. These work in a similar way to view template partials. To use on we need to call partial! on the json object and pass in the path to a partial or just an object, in this case a comment.

This will look for a partial under the app/views/comments directory called _comment.json.jbuilder. In this partial we have access to the same json object and we can do the same thing we’d do in the comment block. We also have access to the comment object here as we passed that in in the partial! call.

/app/views/comments/_comment.json.jbuilder

json.(comment, :id, :name, :content)

This will now display the same JSON we had before.

Alternatives

JBuilder isn’t the only gem that does this kind of thing. At the bottom of the project’s README file is a list of alternatives that are worth considering. RABL is the most popular of these and it’s something we might cover in a future episode.