Paperclip Storage S3 Extension

I recently switched from using attachment_fu to paperclip to store images on S3 in my Rails models. Paperclip is great, as it creates the columns in the model itself without requiring another model (and hence another query to the db). I also use paperclip to store the images uploaded to Amazon’s S3, which works great for me, instead of storing images on the local filesystem.

However, there is one problem that I keep running into time and again. Every few days, I take a dump of the production database and load it in my development environment. Sometimes, I also use the same database in the test environment. The problem, of course, is that unless I duplicate all the files in S3′s storage, I dont see any images, and thus, don’t get nearly the same experience as that of production in either my dev or test environments. Additionally, I do not want to change the bucket configuration in my dev environment to point to the production bucket, as that can create additional problems when I am testing writes and deletes to that bucket.

Wouldn’t it be great that in your dev environment you could still see the images from the production bucket *if* the corresponding image in the dev bucket did not exist? Additionally, if you ever made changes (edits or deletes) to these files, then those changes would be made from the dev bucket and not the production bucket.

So, my friend Shan Bhardwaj, and I ended up writing an extension to the paperclip storage module that does exactly that. You can find the extension at http://github.com/finknottle/Paperclip-Storage-Extension

What this extension does

The paperclip plugin is great to add files to your existing model without requiring an additional model.
The paperclip storage module has a module called S3 which allows you to store your uploaded files in your S3 account.
The buckets can be defined in the configuration YAML file, typically called #{RAILS_ROOT}/config/amazon_s3.yml or
#{RAILS_ROOT}/config/s3.yml.
The configuration file looks like

development:
access_key_id: your_access_key
secret_access_key: your_secret_key
bucket: bucket_name_on_S3

production:
access_key_id: your_access_key
secret_access_key: your_secret_key
bucket: bucket_name_on_S3

The problem though is that when you are developing on your machine, or creating a test machine, but with the production environment, then you want to copy the db from your production machine, and play with the data. At this point, you usually want your files (typically images) to be available for your environment. But at the same time, you don’t want to change the files in your production bucket when you change them in your development or test environment.

This is where this extension comes in. The extension allows you to add two more configuration options to your YAML file. So that, the file then looks like

development:
access_key_id: your_access_key
secret_access_key: your_secret_key
bucket: bucket_name_on_S3
bucket_alt: alt_bucket_name
testing: true

production:
access_key_id: your_access_key
secret_access_key: your_secret_key
bucket: bucket_name_on_S3
bucket_alt: alt_bucket_name
testing: false

You can add the additional two options through a capistrano recipe or a chef recipe, based on your deployment mechanism.

Thus, in your production environment, everything will work as before, all reads and writes will occur on the production bucket defined in the configuration bucket:

However, in your test or dev environment, the reads will be done from the alt_bucket_name if it exists (production
bucket), but the writes and deletes will be done from your bucket (dev bucket).

Installation

You can get the lib from http://github.com/finknottle/Paperclip-Storage-Extension.
Simply add the paperclip_storage_ext.rb file to the #{RAILS_ROOT}/lib/ directory, and require it in the environment.rb file below the Rails Initializer block
require 'lib/paperclip_storage_ext'

If you have questions about this, feel free to drop me a line.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s