Class | ActionController::Responder |
In: |
lib/action_controller/metal/responder.rb
|
Parent: | Object |
Responder is responsible for exposing a resource to different mime requests, usually depending on the HTTP verb. The responder is triggered when respond_with is called. The simplest case to study is a GET request:
class PeopleController < ApplicationController respond_to :html, :xml, :json def index @people = Person.find(:all) respond_with(@people) end end
When a request comes in, for example for an XML response, three steps happen:
1) the responder searches for a template at people/index.xml; 2) if the template is not available, it will invoke <code>#to_xml</code> on the given resource; 3) if the responder does not <code>respond_to :to_xml</code>, call <code>#to_format</code> on it.
The default Rails responder holds semantics for each HTTP verb. Depending on the content type, verb and the resource status, it will behave differently.
Using Rails default responder, a POST request for creating an object could be written as:
def create @user = User.new(params[:user]) flash[:notice] = 'User was successfully created.' if @user.save respond_with(@user) end
Which is exactly the same as:
def create @user = User.new(params[:user]) respond_to do |format| if @user.save flash[:notice] = 'User was successfully created.' format.html { redirect_to(@user) } format.xml { render :xml => @user, :status => :created, :location => @user } else format.html { render :action => "new" } format.xml { render :xml => @user.errors, :status => :unprocessable_entity } end end end
The same happens for PUT and DELETE requests.
You can supply nested resources as you do in form_for and polymorphic_url. Consider the project has many tasks example. The create action for TasksController would be like:
def create @project = Project.find(params[:project_id]) @task = @project.comments.build(params[:task]) flash[:notice] = 'Task was successfully created.' if @task.save respond_with(@project, @task) end
Giving an array of resources, you ensure that the responder will redirect to project_task_url instead of task_url.
Namespaced and singleton resources require a symbol to be given, as in polymorphic urls. If a project has one manager which has many tasks, it should be invoked as:
respond_with(@project, :manager, @task)
Check polymorphic_url documentation for more examples.
ACTIONS_FOR_VERBS | = | { :post => :new, :put => :edit |
controller | [R] | |
format | [R] | |
options | [R] | |
request | [R] | |
resource | [R] | |
resources | [R] |
Display is just a shortcut to render a resource with the current format.
display @user, :status => :ok
For XML requests it‘s equivalent to:
render :xml => @user, :status => :ok
Options sent by the user are also used:
respond_with(@user, :status => :created) display(@user, :status => :ok)
Results in:
render :xml => @user, :status => :created