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: elsif has_empty_resource_definition?
165: display empty_resource, :status => :ok
166: else
167: head :ok
168: end
169: 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 223
223: def default_action
224: @action ||= ACTIONS_FOR_VERBS[request.request_method_symbol]
225: end
If a given response block was given, use it, otherwise call render on controller.
# File lib/action_controller/metal/responder.rb, line 189
189: def default_render
190: @default_response.call
191: 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 210
210: def display(resource, given_options={})
211: controller.render given_options.merge!(options).merge!(format => resource)
212: end
Return a valid empty JSON resource
# File lib/action_controller/metal/responder.rb, line 241
241: def empty_json_resource
242: "{}"
243: end
Delegate to proper empty resource method
# File lib/action_controller/metal/responder.rb, line 235
235: def empty_resource
236: send("empty_#{format}_resource")
237: end
Check whether resource needs a specific definition of empty resource to be valid
# File lib/action_controller/metal/responder.rb, line 229
229: def has_empty_resource_definition?
230: respond_to?("empty_#{format}_resource")
231: end
Check whether the resource has errors.
# File lib/action_controller/metal/responder.rb, line 216
216: def has_errors?
217: resource.respond_to?(:errors) && !resource.errors.empty?
218: end
Returns the resource location by retrieving it from the options or returning the resources array.
# File lib/action_controller/metal/responder.rb, line 180
180: def resource_location
181: options[:location] || resources
182: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.