An alternative to Active Storage: Shrine
Diario del capitán, fecha estelar d257.y38/AB
We are using Shrine as an alternative to Active Storage for our own product, Rosetta. Here's why.
A few days ago, we announced that we're building our first product, Rosetta. You can read the blog post announcing it here: Venturing into Developing Our Own Product.
Rosetta will be our first excursion into developing a full product for ourselves, which can serve a big number of other companies, especially in the HR sector.
Even though we have also recently announced that we're offering Node.js and React services, we're developing Rosetta with Ruby as backend language.
Using Shrine as an alternative to Active Storage
Active Storage is widely used as the go-to solution to upload files to cloud storage services such as Amazon S3, Google Cloud Storage, or Microsoft Azure. Active Storage attaches said files to Active Record objects, and comes as a standard inside Rails since it was first introduced about a year ago.
We have since then adopted Active Storage in our projects by default, but the growing number of issues over time have become a concern. Mainly:
- Can't make uploads public, they are always uploaded privately.
- Can't change the host to use a CDN.
- When trying to save a record with validation errors, the file is still uploaded but not deleted. You end up with orphan files taking up space.
These issues have forced us to look for an alternative.
Enter Shrine.
Shrine is a viable alternative to Active Storage which provides an extensive toolkit for file attachments in Ruby applications. Lately, it's gotten a lot of attention, and its growing popularity is matched by some really nice advantages:
- Lightweight/modular: You can choose the features you need and only those are loaded.
- It's got a system to cache attachments before uploading them. You can use S3 as the cache, with a specific prefix allowing to easily process files (like creating thumbnails) in the background.
- It allows generation of versions both "on the fly" (by providing an endpoint that generates the version the first time is requested) or upon upload. Moreover, this can be customized per uploader. So you can choose depending on how costly it is to generate a version and/or how likely is that someone will end up requesting it.
- Can use a memory store to speed up tests.
What's more, its integration with Rails is really straightforward and its interface is really easy to use and understand.
If you want to read further technical details about this, read the Shrine advantages documentation.
Some quick wins
As a result of using Shrine in our own project, we have found a viable alternative for projects where Active Storage just doesn't cut it. No more one-size-fits-all for the management of file attachments.
Further, I configured the AWS account used by Shrine to have strictly and solely the permissions it needs. To do that, instead of creating a user and just assigning the "S3FullAccess" policy, I have created a custom policy that only grants the S3 permissions needed and only to the development bucket.
We will need to create another one for production and staging. This has the added benefit that it's impossible to modify something in the production bucket by mistake by using the development keys, so it reduced the human error factor.
Not that this is something that can't be done with ActiveStorage. It's independent of the solution we used, but while I was at it, I took the opportunity to do this improvement in security.
I'm sure I'll find more advantages to using Shrine over Active Storage, but I will follow up with more information as soon as I find interesting stuff to share.
Stay tuned!