Search site

Add to Google

Featured Articles
How to cache the output of an XML page in Rails back
Previous article: Search engine friendly link_to function in Rails view


I came into a bit of bother recently when I decided to cache the output of the RSS feed of my website.

Rails has a built-in cache mechanism for pages and fragments, and is great for html and text pages. However, when it comes to caching the output of an XML page (like the output of the RSS engine), it breaks both Internet Explorer and Firefox. They both work fine when the page is not yet cached, but once the cached version is returned in subsequent requests, the XML is simply shown on Firefox as plain text, minus the XML tags. On IE, it simply displays "The page can not be displayed" message. The reason for this is because the Erb processor (responsible for rendering the response data before sending it to the browser) makes the assumption that the output is always either html or text, but never XML. This means it does not set the Content-Type header correctly in the response.

I tried all various render() combinations in the ActionController, but none produce the desired result. Worse, if you use the inline version of render() on the cached text, it crashes the Rails engine solid (this is because the text stored in the cached fragment has already been rendered). In the end, this is the work around I employed, which seems to work fine:

@fragment = read_fragment self.cache_key
if !@fragment.nil?
    # have to render the XML as plain text
    render :text => @fragment
    # this is the hack !
    @response.headers['Content-Type'] = "text/xml"

This seems to work a treat. I guess it should work the same way for PDF, Excel spreasheet etc. but have not yet verified it.

If you know of a better way, or an officially supported way of doing this, please let me know.

Previous article: Search engine friendly link_to function in Rails view

discuss (3 comments)
 by by David at 22 Jul 2006 09:59:36
Hi David,

Are you using page, action or fragment caching in this case?
I need this with action caching, do you believe it will work?


by Manoel Lemos at 20 Sep 2006 23:30:31
Hi Manoel

I was specifically using fragment caching, although theoretically the approach should work for all types of caching, as long as you are able to grab the @response before it goes back to the browser.

For this very reason, action caching is a bit trickier because the controller takes over the rendering. You will need to use an after_filter in order to access the @response object.

by David at 21 Sep 2006 01:15:45
hmn. this looks great, but (as I am a noob) where do you put this little gem of code in your app?
by mongo1515 at 27 Jun 2007 13:33:31
Copyrights © Transcraft Trading Limited 2006.All rights reserved. Bots Rss-rss