Removing Rails formatted routes too soon

Here’s something to watch out for when serving different types of content using the Rails respond_to and :format parameters. Browsers don’t always know exactly what to do when serving non-html content. In my app, we serve many pages as csv as well as html. Since the formatted_ routes are going to be removed from Rails, I stopped defining them in favor of simply using the :format parameter.

This means the url in the browser location bar will NOT end with “.csv”. Don’t do this on Rails 2.2.2 and earlier!

Rails 2.2.2 properly sets the Content-Type to text/csv. But that’s not enough for our browser to know what to do with it. Poking around this morning reveals that Numbers on my MacBook Pro will not open the csv file without an extension. Same issue reported by QA on Windows with IE and Firefox and Microsoft Excel. Same results whether you let the browser open the file in an app directly, or Save As and then open it.

Along with the content-type, the filename and extension needs to be correct.

I fixed this on the server side, by forcing a disposition header the same way send_data does.

respond_to do |format|
  format.html
  format.csv { headers["Content-Disposition"] ||= "attachment; filename=\"#{params[:action] + '.csv'}\"" }
end

Now we get a disposition header, which explicitly tells the browser what type of file it is.

Content-Disposition: attachment; filename="index.csv"

This is ugly. Don’t do it. It won’t be needed when this patch, which removes the formatted_ routes, it released. It seamlessly keeps support for incoming requests such as “/posts.csv” working as they should.

So the moral of the story is: don’t be overzealous and stop using formatted routes yet! When you upgrade your app, just remove the formatted routes from routes.rb and everything will continue to work as it should.