Paperclip and Amazon S3

by Clayton on June 19, 2008

I recently added the ability to give each one of my posts a photo. It makes the entire site a bit less boring and gives it some human feel. I found the excellent paperclip plugin from the thoughtbot guys. This allowed me to easily attach pictures, have them resized and display them along side my posts. However, I ran into some problems with managing the upload files, no worries, Amazon S3 to the rescue.

Capistrano Deployment Problems

Each time you deploy your updated rails app with capistrano, it checks out the code in a new time-stamped directory and symlinks it to a “current” directory. The problem with this setup was that each time I updated my code, the uploaded files would be wiped out. I had a few options:

  1. Tell paperclip to store the files above the document root
    • Pretty simple, have to change the deploy recipe a bit
  2. Change my deploy recipe so “save” the files that have already been uploaded
    • Kinda cumbersome and a little “wrong” feeling
  3. Tell paperclip to store the files on Amazon’s S3
    • No changes to my filesystem or deploy recipe!

Paperclip Setup

In my Post model I’ve got

1
2
3
4
5
6
7
8
9
10
  has_attached_file :photo,
    :styles => {
      :tiny => "35x35",
      :preview => "175x175",
      :large => "300x300"
    }, 
    :storage => :s3,
    :s3_credentials => "#{RAILS_ROOT}/config/s3.yml",
    :path => ":attachment/:id/:style.:extension",
    :bucket => 'lengelzigich_blog_buckit'

I’m telling the paperclip plugin to resize my uploaded image in a few formats and also telling it that I want to store the files using S3 rather than the file system. I’ve added my amazon S3 key/secret code to a simple yaml file and I’m all set. Almost.

Install right_aws gem

Didn’t realize this right away but needed to install the right_aws gem.

{ 6 comments… read them below or add one }

Jimmy Baker February 21, 2009 at 4:58 pm

Another option for you would have been to symlink the folder where you want to store your images. In most cases and files that need to persist across deploys will go in the “shared” folder inside your deploy path.

This little capistrano recipe does just that:

task :after_symlink do
  run "ln -nfs #{shared_path}/images/products #{release_path}/public/images/"
end

This post answered my questions about the s3 storage option. Thanks a bunch!

Travis Roberts May 27, 2009 at 12:54 pm

The newest version of paperclip now has the default filesystem storage path as “:rails_root/public/system/:attachment/:id/:style/:filename”. This solves the problem that you had because, if you use Capistrano, the “system” folder is already symlinked from your “public” folder.

Thanks for the S3 help, though! Just what I was looking for.

Gordon June 5, 2009 at 8:57 pm

Great S3 and Paperclip walkthrough, thanks for the post!

Clayton June 5, 2009 at 9:03 pm

I should really do an updated one of these since it’s so old, but thanks!

Charlie Maffitt June 16, 2009 at 9:24 am

Thanks – I used this post to set up paperclip with s3, and it works, but I do get some application errors if I call @model.attachment.exists? in the code.

The error goes something like “Key can not be blank.”

A workaround is to check to see if @model.attachment_file_name.blank? instead, since it won’t have a file name if the attachment doesn’t exist, but I was wondering if anyone else has had this same problem with referring directly to the attachment, and if so how did you fix it?

Eric October 20, 2009 at 1:27 pm

Awesome, I’ve been meaning to push off my picture storage to S3 on one of my apps for a while, I’m about to finally take the plunge thanks to this. Thanks!

Leave a Comment

Previous post:

Next post: