Rename S3 assets after paperclip hashing

Reading Time: 2 minutes

I just found out about paperclip hashing to keep your styles as a ‘not easy to guess’ url so something like this:


becomes something like this


this way is harder for people to guess your styles, which might be private some how.

This is really simple to set up all you need to do is set up a hash_secret default option for paperclip and add :hash in the asset path in an initializer, like this:

  :path => ":class/:attachment/:hash/:style.:extension",
  :hash_secret => ENV[RANDOM_SECRET]

And voila, now you have complex to guess urls for your assets, but, when you go and check the site you’ll notice that all the images point to non existing files so we need to copy/move/rename all the old files to the new S3 url.

I spent some time finding how to generate the :hash param in the url so I can copy files from the old url into the new one, and I found a method in paperclip attachment model called hash_key, this method receives the syle name and does a Digest interpolating your unique hash_secret and the style name.

So now that we know how to generate the proper url to copy to, we need to actually copy the files, so I came up with this small rake task that uses amazon AWS SDK to copy all files to the new location.

namespace :aws do
  namespace :rename do
    task media: :environment do
      Model.all.each do |m|
        [:original, :medium, :thumb].each do |style|
          s3 =
          key = "model/#{}/#{style}/#{m.attachment_file_name}"
          object = s3.buckets[:bucket_name].objects[key]
          next unless object.exists?
          hash = m.attachment.hash_key style
          copy_key = "m/#{}/#{hash}/#{m.attachment_file_name}"
          puts "Copying to #{copy_key}"
          object.copy_to(copy_key, acl: :public_read)

Please be carefull with the key and copy_key variables I’m using in this snippet since they’re different in each project depending on your path configuration, also, notice how im using acl: :public_read in the copy_to method since those styles being copied are meant for public access and paperclip by default makes them public but copying them using AWS doesn’t so make sure you want those assets either public or private and set the necessary permissions to them.

Note: You can also use move_to method instead of copy_to, but I wouldn’t recommend it because something could go wrong and this way you’ll have some sort of backup.

Scheduled Notifications
De Código, Café y Cervezas 08 – Web Services
Cucumber Tests: Auto Retry Failed
  • Thorsten Claus

    Thats what we need to move from name.extension to a hashed filename.
    In (my) current rails environment this don’t work.
    By starting the rake task it reads ‘uninitialized constant AWS’, even with require ‘aws-sdk-s3’ on top of task. Do you have an idea why AWS is not initialized?

    Even better – maybe you can fork the paperclip lib and add this code to their paperclip rake tasks?
    Good work, but I’d love to see it running.

    • softr8

      Try Downgrading aws-sdk gem to a previous version, paperclip depends on AWS constant which is not defined anymore in the new aws-sdk gem

Copy link
Powered by Social Snap