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.
Initializes a new responder an invoke the proper format. If the format is not defined, call to_format.
# File lib/action_controller/metal/responder.rb, line 111 111: def self.call(*args) 112: new(*args).respond 113: end
# File lib/action_controller/metal/responder.rb, line 90 90: def initialize(controller, resources, options={}) 91: @controller = controller 92: @request = @controller.request 93: @format = @controller.formats.first 94: @resource = resources.last 95: @resources = resources 96: @options = options 97: @action = options.delete(:action) 98: @default_response = options.delete(:default_response) 99: end
Main entry point for responder responsible to dispatch to the proper format.
# File lib/action_controller/metal/responder.rb, line 117 117: def respond 118: method = :"to_#{format}" 119: respond_to?(method) ? send(method) : to_format 120: end
All other formats follow the procedure below. First we try to render a template, if the template is not available, we verify if the resource responds to :to_format and display it.
# File lib/action_controller/metal/responder.rb, line 135 135: def to_format 136: default_render 137: rescue ActionView::MissingTemplate => e 138: api_behavior(e) 139: end
This is the common behavior for “API” requests, like :xml and :json.
# File lib/action_controller/metal/responder.rb, line 155 155: def api_behavior(error) 156: raise error unless resourceful? 157: 158: if get? 159: display resource 160: elsif has_errors? 161: display resource.errors, :status => :unprocessable_entity 162: elsif post? 163: display resource, :status => :created, :location => api_location 164: else 165: head :ok 166: end 167: end
By default, render the :edit action for HTML requests with failure, unless the verb is POST.
# File lib/action_controller/metal/responder.rb, line 221 221: def default_action 222: @action ||= ACTIONS_FOR_VERBS[request.request_method_symbol] 223: end
If a given response block was given, use it, otherwise call render on controller.
# File lib/action_controller/metal/responder.rb, line 187 187: def default_render 188: @default_response.call 189: end
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
# File lib/action_controller/metal/responder.rb, line 208 208: def display(resource, given_options={}) 209: controller.render given_options.merge!(options).merge!(format => resource) 210: end
Check whether the resource has errors.
# File lib/action_controller/metal/responder.rb, line 214 214: def has_errors? 215: resource.respond_to?(:errors) && !resource.errors.empty? 216: end
Returns the resource location by retrieving it from the options or returning the resources array.
# File lib/action_controller/metal/responder.rb, line 178 178: def resource_location 179: options[:location] || resources 180: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.