I am converting a Rails 2 application to Rails 3. I currently have a controller set up like the following:
class Api::RegionsController < ApplicationContr
I have been fighting this issue today, and I settled for the before_filter
solution you mentioned yourself in your comment:
before_filter :default_format_xml
# Set format to xml unless client requires a specific format
# Works on Rails 3.0.9
def default_format_xml
request.format = "xml" unless params[:format]
end
This solution also allows for taking into account content negotiation, which was a factor in my case. I wanted web browsers to get an HTML view but custom clients (with no Accept headers) to get JSON. This solved my problem:
before_filter :default_format_json
def default_format_json
if(request.headers["HTTP_ACCEPT"].nil? &&
params[:format].nil?)
request.format = "json"
end
end
An easy but ugly solution is to override html content type handling to render xml:
respond_to :html, :xml, :json
def index
@regions = Region.all
respond_with @regions do |format|
format.html { render :xml => @regions }
end
end
Well, as you have been noted that each format should be explicitly rendered with specific render call, you can also avoid any request with unknown or unsupported format, for my example called default, as follows:
rescue_from ActionController::UnknownFormat, with: ->{ render nothing: true }
You can simulate the unknown format call with the simple browser (exmp.firefox) line (in development mode):
http://localhost/index.default
It will call :index
method of a root controller with format called as default.
If I understand what you are trying to do, you probably can solve the issue by setting the default resource format to XML. This will allow your users to make requests using 'api/regions' and have the response default to XML. Take a look at look at the 'Controller Namespaces and Routing' and the 'Defining Defaults' sections at:
http://guides.rubyonrails.org/routing.html
You could do something like the following in routes.rb:
namespace "api" do
resources :regions, :defaults => { :format => 'xml' }
end
Then you should be able to have the following work for your controller methods:
class Api::RegionsController < ApplicationController
respond_to :xml, :json
def index
respond_with(@regions = Region.all)
end
end
Not what you're after but related:
def index
@regions = Region.all
respond_to do |format|
format.json { render :json => @regions }
format.any(:xml, :html) { render :xml => @regions }
end
end
"Respond to also allows you to specify a common block for different formats by using any"