Refile: Fixing Ruby File Uploads

This post was originally published on the Elabs blog, before Elabs and Varvet joined forces.

Six years ago, Merb was on the scene. I was one of its acolytes. I wanted a nice upload plugin for Merb. Since I had some experience in this area from writing (never popular) UploadColumn, I wrote one. It was called merb-upload, and my intention was for this to eventually become part of merb-more. You’ve probably never heard of merb-upload, but you may have heard of what it eventually became. It slowly grew Rails support, and to reflect the diversification, I renamed it CarrierWave.

It actually took a while for CarrierWave to become succesful, so it was the new kid for the long time, but it’s actually only about a year younger than Paperclip. While both of these libraries, the two most popular for file uploads by far, have changed drastically over time, they are nevertheless both over six years old.

A lot has changed since then.

Over the years I’ve been contemplating what I would have done differently if I had to do it all over again.

  1. CarrierWave’s killer feature is fixing file uploads to work even if validations failed and the form needs to be redisplayed. Unfortunately this has never worked reliably when files were uploaded to S3.

  2. Processing files on upload can be prohibitively expensive, and CarrierWave doesn’t provide a good solution to this. When the size of an image should be changed CarrierWave requires re-processing all files. Dragonfly has a much better solution to this problem: processing images on the fly and serving them up directly, behind a CDN.

  3. Direct to S3 uploads are cumbersome. I find myself needing this time after time, and while there are bolt-on solutions, nothing really feels very solid.

  4. The internal design of CarrierWave is just far too flexible and strange. Uploader classes, while a nice relief from the monstrous configuration in model classes that other plugins require, are also quite brittle. I also found myself never actually using any of the insane flexibility that CarrierWave provides. It’s really hard to figure out what actually happens inside CarrierWave.

  5. The integrations have changed. When CarrierWave was written, Ruby web frameworks were different than they were today. Rails 2.3 with support for Rack wasn’t released until a year after its inception. Merb was a serious contender. As a result, there’s a lot of boilerplate in CarrierWave which isn’t really necessary.

All of these problems have been on my mind off and on again over the past couple of years. Even though I haven’t been involved in the CarrierWave project in years, I still found myself unsatisfied with its current state, and with the status quo of file uploads in general.

So I wrote a new one. This is my third attempt at a file upload plugin, and I’m hoping that this time, maybe I got it right.

It probably isn’t for everyone. It’s far, far more opinionated than CarrierWave or Paperclip. I don’t expect it to outright replace either. But if you’re looking for something which is simple, where you can get direct to S3 uploads with the addition of a single config option, where you don’t really have to think about how and where files are stored. This may be the one for you.

It’s called Refile. Please check it out and let me know what you think. All feedback and especially all contributions are very welcome.