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’
end

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

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

/albums/xxx/artwork.jpg?size=100

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

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:

/albums/xxx/artwork/size.jpg

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’
end

On 10/13/07, Luke R. [email protected] wrote:

expected.
But what about when I specify a size? I want these to be cached
take no notice of it. Can anybody help me with this?


Cheers!

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
end

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
end
end

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 = Artwork.new(@album, size = params[:id])

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

end

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

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
is:

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

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).