With the default routing, the request /posts/:id gets mapped to the "show" action with :format => "html"
. I am using some xhtml elements in my show action which don't get rendered correctly unless the :content_type is set to xml. I am currently getting around this by rendering show.xml.erb and setting the content_type manually as follows:
format.html { render :template => "/posts/show.xml.erb",
:locals => {:post => @post}, :content_type => "text/xml" }
This seems silly though. How can I change routes.rb
so that /posts/:id is routed with format=>"xml"
? Thanks.
Default format for requests:
You can set the default format of a given route to xml using the defaults hash.
Examples:
# single match defaulting to XML (/plots/1 is the same as /plots/1.xml)
match 'posts/:id' => 'posts#show', :defaults => { :format => 'xml' }
# using resources, defaulting to XML (all action use XML by default)
resources :posts, :defaults => { :format => 'xml' }
# using resources and mixing with other options
resources :posts,
:only => [:new, :create, :destroy],
:defaults => { :format => 'xml' }
It's always a good idea to search the official Ruby on Rails routing guide, it's fairly in-depth and a very good first-stop resource for any routing issues.
If you only want to support one format and treat all requests as that format, you could use a filter to change it:
before_filter :set_format
def set_format
request.format = 'xml'
end
Rails 4 and 5: In your controller (e.g. ApplicationController
if all whole application uses same format) add following:
before_action :set_default_request_format
def set_default_request_format
request.format = :json unless params[:format]
end
For Rails 3 and older use before_filter
instead of before_action
.
I'm finding weird behaviour in Rails 5 if you use this:
{ format: :json }
In your config/routes.rb
then even if JSON isn't set in your accept header, it still coerces the request to a JSON request, including for controller tests that have the as: :html
option set. It's not really a big deal for me, so I'm not going to dig into why this is, but if someone figures it out, let me know and I'll update this answer.
If you want to set the default format for a route, use defaults
option:
resources :posts, defaults: { format: 'xml' }
But if you want to enforce every request to return a specific format, use constraints
option:
resources :posts, constraints: lambda { |req| req.format == 'xml' }
See the documentation: http://edgeguides.rubyonrails.org/routing.html#request-based-constraints