module ActionController::MimeResponds

def respond_to(*mimes)

end
format.html.phone # this gets rendered
format.html.none
respond_to do |format|

`:tablet` variant declared, the `:phone` variant will be used:
This will work similarly to formats and MIME types negotiation. If there is no

request.variant = [:tablet, :phone]

You can also set an array of variants:

end
end
variant.phone { render html: "phone" }
variant.any(:tablet, :phablet){ render html: "any" }
format.html do |variant|
respond_to do |format|

and block syntax:

end
format.html.phone { render html: "phone" }
format.html.any { render html: "any" }
respond_to do |format|

It works for both inline:

Variants also support common `any`/`all` block that formats have.

end
format.html.none { render "trash" }
format.html.phone { redirect_to progress_path }
format.js { render "trash" }
respond_to do |format|

variants using the inline syntax:
When you're not sharing any code within the format, you can simplify defining

app/views/projects/show.html+phone.erb
app/views/projects/show.html+tablet.erb
app/views/projects/show.html.erb

Provide separate templates for each format and variant:

end
end
variant.none { special_setup } # executed only if there is no variant set
variant.phone { extra_setup; render ... }
variant.tablet # renders app/views/projects/show.html+tablet.erb
format.html do |variant|
respond_to do |format|

Respond to variants in the action just like you respond to formats:

request.variant = :tablet if /iPad/.match?(request.user_agent)

You can set the variant in a `before_action`:

and desktop browsers. Variants make it easy.
We often want to render different html/json/xml templates for phones, tablets,

`:phone`, or `:desktop`.
The request variant is a specialization of the request format, like `:tablet`,

Formats can have different variants.

end
format.any { redirect_to support_path }
format.html
respond_to do |format|

any format requested by the user:
`any` can also be used with no arguments, in which case it will be used for

render json: @people

Or if the format is json:

render xml: @people

In the example above, if the format is xml, it will render:

end
end
format.any(:xml, :json) { render request.format.to_sym => @people }
format.html
respond_to do |format|

@people = Person.all
def index

by using `any`:
`respond_to` also allows you to specify a common block for different formats

Mime::Type.register "image/jpeg", :jpg

register your own handlers in `config/initializers/mime_types.rb` as follows.
If you need to use a MIME type which isn't supported by default, you can

defaults, life will be much easier.
in a single root node), but if you just go with the flow and accept Rails'
to describe multiple entities in a single request (i.e., by wrapping them all
Note that you can define your own XML parameter parser which would allow you

data.
find or create the company, and then create the new person with the remaining
person. Then, in the action, we extract the company data from the request,
In other words, we make the request so that it operates on a single entity's



...

...


And, like this (xml-encoded):

person[name]=...&person[company][name]=...&...

so that the request looks like this (url-encoded):
process) can only contain a single root-node. So, we have to rearrange things
This is because the incoming XML document (if a web-service request is in

@company = Company.find_or_create_by(name: company[:name])
company = params[:person].delete(:company)

Note, however, the extra bit at the top of that action:



...
...
...

...
...


person's company in the rendered XML, so you get something like this:
render the created person as XML, but with a twist: we also include the
template associated with this action. Lastly, if the client wants XML, we
they want JavaScript, then it is an Ajax request and we render the JavaScript
If the client wants HTML, we just redirect them back to the person list. If

end
end
format.xml { render xml: @person.to_xml(include: @company) }
format.js
format.html { redirect_to(person_list_url) }
respond_to do |format|

@person = @company.people.create(params[:person])
@company = Company.find_or_create_by(name: company[:name])
company = params[:person].delete(:company)
def create

Here's the same action, with web-service support baked in:

end
redirect_to(person_list_url)

@person = @company.people.create(params[:person])
@company = Company.find_or_create_by(name: params[:company][:name])
def create

look like this:
company (by name) if it does not already exist, without web-services, it might
Supposing you have an action that adds a new person, optionally creating their

format from the HTTP Accept header submitted by the client.)
the list of people in XML format." (Rails determines the desired response
just respond as we would have before, but if the client wants XML, return them
What that says is, "if the client wants HTML or JS in response to this action,

end
end
format.xml { render xml: @people }
format.js
format.html
respond_to do |format|

@people = Person.all
def index

Here's the same action, with web-service support baked in:

end
respond_to :html, :js
@people = Person.all
def index

explicitly enumerated:
That action implicitly responds to all formats, but formats can also be

end
@people = Person.all
def index

a list of people might look something like this:
Without web-service support, an action which collects the data for displaying
def respond_to(*mimes)
  raise ArgumentError, "respond_to takes either types or a block, never both" if mimes.any? && block_given?
  collector = Collector.new(mimes, request.variant)
  yield collector if block_given?
  if format = collector.negotiate_format(request)
    if media_type && media_type != format
      raise ActionController::RespondToMismatchError
    end
    _process_format(format)
    _set_rendered_content_type(format) unless collector.any_response?
    response = collector.response
    response.call if response
  else
    raise ActionController::UnknownFormat
  end
end