I just found out about paperclip hashing to keep your styles as a 'not easy to guess' url so something like this:
products/1/original/image.jpg
becomes something like this
products/1/sadGFASgoaw4eaw40q2asfq23/image.jpg
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:
Paperclip::Attachment.default_options.update({
: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 = AWS::S3.new
key = "model/#{m.id}/#{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/#{m.id}/#{hash}/#{m.attachment_file_name}"
puts "Copying to #{copy_key}"
object.copy_to(copy_key, acl: :public_read)
end
end
end
end
end
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.