Question

I understand how respond_to works when it's called with something like this:

def index
  @users = User.all
  respond_to do |format|
    format.html
    format.json { render json: @users }
  end
end

But I've seen some apps which pass respond_to a list of symbols, outside of the controller methods, e.g.:

class UsersController < ApplicationController

  respond_to :html, :json

  def index
    # blah blah bah
  end
end

What does this do? I've been playing around with it in one of my controllers and I can't figure out what difference it makes.

Was it helpful?

Solution

For a given controller action, #respond_with generates an appropriate response based on the mime-type requested by the client.

If the method is called with just a resource, as in this example -

class PeopleController < ApplicationController
  respond_to :html, :xml, :json

  def index
    @people = Person.all
    respond_with @people
  end
end

then the mime-type of the response is typically selected based on the request's Accept header and the set of available formats declared by previous calls to the controller's class method respond_to. Alternatively the mime-type can be selected by explicitly setting request.format in the controller.

If an acceptable format is not identified, the application returns a '406 - not acceptable' status. Otherwise, the default response is to render a template named after the current action and the selected format, e.g. index.html.erb. If no template is available, the behavior depends on the selected format:

for an html response - if the request method is get, an exception is raised but for other requests such as post the response depends on whether the resource has any validation errors (i.e. assuming that an attempt has been made to save the resource, e.g. by a create action) -

If there are no errors, i.e. the resource was saved successfully, the response redirect's to the resource i.e. its show action.

If there are validation errors, the response renders a default action, which is :new for a post request or :edit for patch or put.

Thus an example like this -

respond_to :html, :xml

def create
  @user = User.new(params[:user])
  flash[:notice] = 'User was successfully created.' if @user.save
  respond_with(@user)
end

is equivalent, in the absence of create.html.erb, to -

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 }
    else
      format.html { render action: "new" }
      format.xml { render xml: @user }
    end
  end
end

for a javascript request - if the template isn't found, an exception is raised.

for other requests - i.e. data formats such as xml, json, csv etc, if the resource passed to respond_with responds to to_, the method attempts to render the resource in the requested format directly, e.g. for an xml request, the response is equivalent to calling render xml: resource.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top