Layouts with JBuilder and rails-api

Rails-api has been merged into normal rails, but this is what I’m working with. I’m fairly certain the process will be identical for someone using the new setup!

I wanted to build an API whose responses had a reusable wrapper, just like an HTML response can be wrapped in a reusable header and footer. The process to do this is easy, but not totally neat, for reasons I’ll get into.

Anyways, here’s what you need.

# app/controllers/application_controller.rb
class ApplicationController < ActionController::API
  include ActionController::ImplicitRender
  include ActionView::Layouts
end
# app/views/application.json.jbuilder
json.head("This will appear in every response")
json.body(JSON.parse(yield))

JSON.parse(yield) stands in for the normal yield you are used to when rendering HTML with erb or what have you.

This code is not ideal because the use of JSON.parse(yield) means that the body of your JSON response is parsed twice. It is hella inefficient.

I’ve done a fair amount of research, and it seems this is simply a limitation of JBuilder. This Github conversation confirms this. If anyone hears of a good solution or workaround, please let me know! And I think ActiveModel::Serializer is not the way for me, but I would love to be convinced!

I suppose you don’t even need to include ActionController::ImplicitRender but it has made my life a whole lot easier! It means you don’t have to specify which jbuilder file to load at the end of a controller; Rails will try to figure out which one based on naming conventions as it does with normal erb views. If your goal is to try and get rails-api to behave like Rails but with JSON instead of HTML, then you need ImplicitRender.

Advertisements

Leave a comment

Filed under Uncategorized

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s