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.