Categories: archive |code

Simple API in Rails 3 using respond_to and respond_with

Yesterday I showed you how to create a simple JSON API in Django. Today I’m going to show you how to do the same thing in Rails 3.

Whereas in Django, by default you have to check for the specific HTTP_ACCEPT header you want to work with, in Rails, you don’t. This is known as Content Negotiation.

Content Negotiation in Rails

So rather than having an if statement checking for the specific accept header, you just use respond_to and respond_with. In Rails 2.X, you would do something like so:

class UsersController < ApplicationController::Base

  def index
    @users = User.all
    respond_to do |format|
      format.html
      format.xml { render :xml => @users }
      format.json { render :json => @users }
    end
  end

  def create
    @user = User.create(params[:user])
    respond_to do |format|
      format.html { redirect_to users_url }
      format.xml { render :xml => @user }
      format.json { render :json => @user }
    end
  end

end

Notice the respond_to block. In it, you just tell Rails which format to use when expecting a certain format.

In Rails 3, it’s even easier. Using respond_with, you can now do:

class UsersController < ApplicationController::Base

  respond_to :html, :xml, :json

  def index
    respond_with(@users = User.all)
  end

  def create
    @user = User.create(params[:user])
    respond_with(@user, :location => users_url)
  end
end

You can read more details on how to use respond_with on Ryan Daigle’s blog and about ActiveModel on the Engine Yard blog. In detail, Yehuda explains that the “available providable formats are transparently determined by introspecting the object”. To me, this is great as it’s one less require or import statement to worry about.

Content Negotiation in Django

James Bennett wrote an excellent article on doing content negotiation in Django here. It is based on Daniel Lindsley’s work here, which was “loosely based around similar functionality, called respond_to in Rails”. I haven’t tried the code in the articles yet, but the idea looks very good and will probably provide me with what I want in Django without having my code splattered with if statements for the sake of content negotiation.