What's New in Edge Rails: Cleaner RESTful Controllers w/ respond_with
This feature is schedule for: Rails v3.0
REST is a first-class citizen in the Rails world, though most of the hard work is done at the routing level. The controller stack has some niceties revolving around mime type handling with the respond_to facility but, to date, there’s not been a lot built into actionpack to handle the serving of resources. The addition of respond_with (and this follow-up) takes one step towards more robust RESTful support with an easy way to specify how resources are delivered. Here’s how it works:
Basic Usage
In your controller you can specify what resource formats are supported with the class method respond_*to*. Then, within your individual actions, you tell the controller the resource or resources to be delivered using respond_*with*:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
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 |
This will match each supported format with an appropriate response. For instance, if the request is for /users.xml then the controller will look for a /users/index.xml.erb view template to render. If such a view template doesn’t exist then it tries to directly render the resource in the :xml format by invoking to_xml (if it exists). Lastly, if respond_with was invoked with a :location option the request will be redirected to that location (as in the case of the create action in the above example).
So here’s the equivalent implementation without the use of respond_with (assuming no index view templates):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
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 |
You can see how much boilerplate response handling is now handled for you especially if it’s multiplied over the other default actions. You can pass in :status and :head options to respond_with as well if you need to send these headers back on resources rendered directly (i.e. via to_xml):
1 2 3 4 5 6 7 8 |
class UsersController < ApplicationController::Base respond_to :html, :xml, :json def index respond_with(@users = User.all, :status => :ok) end end |
Per-Action Overriding
It’s also possible to override standard resource handling by passing in a block to respond_with specifying which formats to override for that action:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class UsersController < ApplicationController::Base respond_to :html, :xml, :json # Override html format since we want to redirect to a different page, # not just serve back the new resource def create @user = User.create(params[:user]) respond_with(@user) do |format| format.html { redirect_to users_path } end end end |
:except And :only Options
You can also pass in :except and :only options to only support formats for specific actions (as you do with before_filter):
1 2 3 4 5 |
class UsersController < ApplicationController::Base respond_to :html, :only => :index respond_to :xml, :json, :except => :show ... end |
The :any Format
If you’re still want to use respond_to within your individual actions this update has also bundled the :any resource format that can be used as a wildcard match against any unspecified formats:
1 2 3 4 5 6 7 8 9 10 11 12 |
class UsersController < ApplicationController::Base def index @users = User.all respond_to do |format| format.html format.any(:xml, :json) { render request.format.to_sym => @users } end end end |
So all in all this is a small, but meaningful, step towards robust controller-level REST support. I should point out that the contributor of this patch is José Valim who has authored the very robust inherited_resources framework that already has support for respond_with-like functionality and many more goodies. If you’re on the search for a solid RESTful controller framework to accompany Rails’ native RESTful routing support I would suggest you take a look at his fine work.
tags: ruby,
rubyonrails
- Person:
- Programming Language:
- Technology:


Recent comments
1 year 23 weeks ago
1 year 23 weeks ago
1 year 25 weeks ago
1 year 27 weeks ago
1 year 42 weeks ago
1 year 45 weeks ago
1 year 45 weeks ago
1 year 45 weeks ago
1 year 46 weeks ago
1 year 48 weeks ago