ruby-on-railsrubydragonfly-gem

Dragonfly and Short URLs


I'm using Dragonfly in a project that returns a large stream of photos and was looking to optimize the URLs. I'm currently getting image URLs like:

http://localhost:3000/media/BAhbCFsHOgZmSSJgZmRlL2ZkZTAxYzQ0LTM4Y2UtNGU0ZS1iOWRlLWUwZmUxNWUwN2JmMC83Mzk1NmZlMC05ZTA5LTQzNWUtODUyMC00MzFlYzQxMzQ1OTQvb3JpZ2luYWwuanBlZwY6BkVUWwg6BnA6CnRodW1iSSIMMjQweDI0MAY7BkZbCTsHOgxjb252ZXJ0SSIQLXF1YWxpdHkgODAGOwZGMA/240x240.jpg

Which is over 256 bytes. I'd like something like:

http://localhost:3000/media/1024/240x240_medium.jpg

That is conforming to:

/media/:id/:format

How would I go about adding this when using Dragonfly and Rails such that :format maps to a chain of operations and :id is used to find the model or image? Thanks!

Edit:

I've added custom Mime::Typefor each of the formats I need and have the following working:

# config/routes.rb
match "/photos/:id/:style", to: "photos#show", as: :media

# app/controllers/photos_controller.rb
def show
  @photo = Photo.find(params[:id])

  respond_to do |format|
    format.html # show.html.erb
    format.jpg { cache('public', 86400); redirect_to @photo.url(params[:style], 'jpg') }
    format.png { cache('public', 86400); redirect_to @photo.url(params[:style], 'png') }
    format.gif { cache('public', 86400); redirect_to @photo.url(params[:style], 'gif') }
  end
end

# app/views/photos/show.html.erb
<%= image_tag media_path(id: @photo.id, style: 'small', format: 'png') %>

However this results in a 302 for each image (but otherwise works fine). Is it possible to handle this as a render or somehow do an internal redirect (i.e. not require the client to make duplicate requests)?


Solution

  • you shouldn't need to use a controller action - you can use a dragonfly endpoint - see http://markevans.github.com/dragonfly/file.URLs.html#Routed_Endpoints

    e.g.

    match '/photos/:id/:style.:format' => Dragonfly[:images].endpoint { |params, app|
      Photo.find(params[:id]).image.thumb(params[:style]).encode(params[:format])
    }
    

    or something like that (haven't tried the above code but it'll be something along those lines)