Restful Resource routes with parameters and page caching

I'm trying to set up a restful route where an Album resource has a
singletone Artwork resource. Sounds simple enough:

map.resources :albums do |album|
    album.resource :artwork,
      :controller => 'artwork', :format => 'jpg'

With the above routing config, /albums/xxx/artwork.jpg works as

However, my artwork controller also has an option to resize the image
if a :size parameter is given. This also works:


However, I want to cache the resized artwork using Rails caching.
Adding caches_page :show works and the cached file is saved under

But what about when I specify a size? I want these to be cached
individually. Specifying size as a query string parameter means the
size is ignored when caching takes place (it is always stored as
artwork.jpg). What I really need is to be able to move the size
parameter into the URL, so it looks something like this:


This would mean page caching does what I want it to do. However I
cannot see any easy way of moving size into the URL using
map.resource. I can set up a custom route but any restful url helpers
take no notice of it. Can anybody help me with this?

Umm..I'm not a fan of nested resources, so I don't know how this would
behave here, but try using path_prefix

map.resources :albums do |album|
   album.resource :artwork, :controller => 'artwork', :format =>
'jpg', :path_prefix => ':size'

I'm not sure that path_prefix is what I need here; either way, I
managed to get this working by treating size as another resource under
artwork. So in essence:

An album has ONE artwork (singleton resource).

map.resources :albums do |album|
  album.resource :artwork

That single piece of artwork can be represented in a number of
different sizes (could be fixed, but in my case its arbitrary):

map.resources :albums do |album|
  album.resource :artwork do |artwork|
    artwork.resources :size

However, because the controller code to resize the image was so simple
(it was all abstracted to the model layer), I was able to handle both
the singleton artwork resource and its various sizes with a single
ArtworkController#index action:

class ArtworkController < ApplicationController
  before_filter :load_album
  caches_page :show

  def show
    @artwork =, size = params[:id])

    send_data @artwork.to_blob,
      :disposition => 'inline',
      :type => @artwork.content_type

    def load_album
      @album = SlimServer::Album.find(params[:album_id])

The only thing here that is slightly confusing is that the size we
want arrives as params[:id]; this wouldn't be so confusing if I was
using a separate AlbumSizesController I guess so I can live with it
(hence I've added the variable hint to the parameter).

The final routing config, with controller names and formats specified

map.resources :albums do |album|
  album.resource :artwork, :controller => 'artwork', :format => 'jpg'
do |artwork|
    artwork.resources :sizes,
      :controller => 'artwork', :format => 'jpg'

I can now access the raw unaltered artwork using /album/xxx/
artwork.jpg and a specific size at /album/xxx/artwork/sizes/xxx.jpg.

Hope this helps anyone with a similar issue.

Small correction the above post, the following block of code should
have artwork.resources :sizes (plural).