Active Storage: Lessons Learned

I just finished a project to migrate one of our projects from using Anaconda for file attachments to ActiveStorage. These are things I've learned, mostly for my own reference, but perhaps they can be of help to others.

Note: This is all in the context of Rails 5.2.0

Direct Uploads Can Be Fussy

We're using direct-to-S3 uploads for our files, and there are still times where things just don't work. Almost always everything is fine on a second try, but it feels like the error handling just isn't all there yet. This is especially true for us on pages with multiple uploads.

AWS Checksums Don't Always Work for Us

This is likely our own bug, or a bug in our systems, but we've run into a few instances now where we get 400 errors back from AWS. After contacting support, they're all mismatched checksums on the data. We haven't been able to reproduce this enough to figure out the cause.

Variants Aren't Stored in the DB

When you're working with variants, they aren't stored in the DB. They're checked for existance every time you try to reference them. This has performance implications.

ActiveStorage Is Not Currently Optimized For Things You Want To Cache

In order to get some decent caching of our files, we've had to build our own controller to load and return actual file contents of the variant from S3, with all the cache control headers included. Doing the file-contents-passthru in this way isn't ideal, but right now ActiveStorage doesn't support public acls or non-expiring url generation. There are some hacks to get around this, but I know better than to hack around a core piece of Rails. So, for now, we just have code that looks like this, which works wonderfully (but should be built-in functionality):

raise "Invalid Object/Variant combination" unless valid_variant?

if @variant.nil?
  render plain: "", status: 404

send_data open(@variant.service_url).read, filename: "#{@variant.blob.filename}"

I'm confident these features will be improved in the future, but as of 5.2.0, this is still a pain.

I Think There's Some Kind of Bug in Safari Related to XMLHTTPRequests And Rails ActiveStorage Forms

If you have a form with a file field in it, and that field is using direct upload, and you don't choose a file but then submit the form, Safari sends a bad request. It seems that it fails to send all the data. Nginx reports client prematurely closed stream: only X out of Y bytes of request body received. It all works perfectly in Chrome every time. Maybe this is just a Safari (11.1) bug, but I have not been able to find a fix. For now, our forms all exist in our admin control panel, so we can work around this. I posted on Stack Overflow about this.