Since the deprecation of paperclip, and release of Active Storage in Rails 5.2, I think it is the right time to learn active storage which provides almost anything that paperclip provided us so far. From creating a style which is called “variant” in case of active storage.
we will start implementing active storage from scratch to our rails application.
Got your laptop/pc ready ??
Let’s start implementing it. I have initialised fresh Rails 5.2 application on my laptop.
Active storage uses two tables named
Run the following command:
This will generate a migration:
2018xxxxxxxxxxx_create_active_storage_tables.active_storage.rb that has the code to create two table as mentioned above.
For every service that you use for storage Rails 5.2 introduces
config/storage.yml for the purposes of storing keys. Have a look at
For local, files storage is defined as:
storage folder which is provided in Rails 5.2.
With so many options, provided to use within a single application, you have to specify which one to use in that specific environment.
For development environment, add following line to
config.active_storage.service = :local
This will tell rails the we will be using
local configuration in development environment.
Mirroring can also be used with Rails 5.2 which I will be covering in different tutorial 😉.
Attaching Files to record
Active storage provides a class method
has_one_attached which is similar to
has_attached_file provided by paperclip.
has_one_attached provided one-to-one mapping between records and files.
So, Let add
has_one_attached :avatar to our user model.
I have created a form to create new user in our application.
So, to save some time I have created
users migration with
Here is the code for it:
Users listing page with code:
Accessing Attached File
Attached file can be accessed by
user.avatar , and you can directly use it with
image_tag(user.avatar) like so.
Creating variants of attached image.
To enable image processing, you have to include:
image_processing gem in Gemfile.
gem 'image_processing', '~> 1.2'
The default processor is
MiniMagick but you can use
When the browser hits the variant URL, Active Storage will lazily transform the original blob into the specified format and redirect to its new service location.
<%= image_tag user.avatar.variant(resize: "50x50") %>
Refresh your page your user’s image should be resized to 100 x 100 in size. See the difference in following image.
Deleting associated avatar
Deleting associated avatar is as simple as doing:
to do it via asynchronous
Diving little deeper
So, Active Storage works just as fine as any other gem. It does image processing on the fly and saves it storage folder ( in case local disk is defined as storage in
Comparison with other storage solution:
Active Storage uses
attachment models backed by Active Record, which is pretty good, that means you don’t need to add columns to existing model’s table.
By looking at the
schema.rb file one can easily guess that active storage uses a polymorphic association via
Attachment join model which then connects to
Lets have a look at the console logs while we are creating a new user instance.
So what happens is, as soon as you create a new instance of model
User in our case it creates
checksum of that file , store it into
Then, it creates entry of the associated model i.e
Also, notice that it creates an
ActiveJob what is this for ?? 🤔
This active job analyses the uploaded file in background and finally updates its metadata, like in the below image:
- Always use
purge_laterwhile deleting associated file,
purgecan be really slow.
purge_laterwill create a job to delete the attachment from blobs table and storage as well.
- Note that to create a variant it’s necessary to download the entire blob file from the service and load it into memory. The larger the image, the more memory is used. Because of this process, you also want to be considerate about when the variant is actually processed.
- Active storage creates a get request for each file that you are rendering to the page.