I’m moving a side project over to Rails 3, and I purposely chose a set of technologies that I hadn’t used yet.
I’ll post about the general experience of this project later, but suffice it to say I’m liking this stack a lot. But this post is specifically about using CarrierWave to handle file uploads.
CarrierWave is similar to Paperclip, however it already supported Rails 3 & Mongoid, so I decided to check it out. It creates the notion of uploaders and places them in a folder next to your models, controllers, views. Each uploader class defines the settings post-processing options for these uploads. I like keeping these separate from the model (instead of how Paperclip does it).
Here is a sample PicUploader that I’m using:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
I’m storing these images in S3, but in order to process the file upload & do post-processing on an image,
it has to first be uploaded to a temp folder. I had to change this
cache_dir to reflect heroku’s temp folder.
Note also that it has support for RMagick (or MiniMagick) in order to do post-processing on the file to resize it to your needs. Here I’m resizing the file to best-fit a 600x600 square (maintaining aspect ratio). I also have 2 thumbnail sizes that clip the image in order to fill an exact square. All of this happens for me when I upload an image.
In order to utilize these files in your model, you have to import the necessary ORM adapter file so that when you save your model the filename gets saved with it. Here is an example model using the mongoid adapter.
1 2 3 4 5 6 7 8 9 10 11
When a category is saved, the uploader processes all of the sizes we need & stores them all in S3. The category can then access these image URLS simply by doing this:
If you need to handle images in your site, you can’t really beat the simplicity of this.
It hasn’t all been sunshine & roses, however. I have another model that accepts multiple images, so I made a
Photo model in order to capture the file & an associated caption. My Item model
It also is set up to
accept_nested_attributes_for :photos, so that I can post multiple photos along with
an item form.
Unfortunately, the mongoid adapter which gives you the
mount_uploader behavior, only works when you call
save directly on that object. Since my photos were being saved by it’s parent document, the upload never
happened. It looks like this is a bug with CarrierWave, and I’m looking at potential ways of contributing a fix. Right now, I’m manually pulling out the photos & saving them one-by-one after an item is saved, but that isn’t a great solution.