DEV Community

Mike Rogers ✈️
Mike Rogers ✈️

Posted on

Resize Images with Active Storage in Rails

We used to have to use gems like Carrierwave & Paperclip to upload files & manipulate images in Ruby on Rails. However we now have a fantastic library built into Rails called Active Storage which handles that for us.

 Setting up Active Storage

The first thing you need to do is run the install script, which will create a migration to add the Active Storage tables to your database.

$ rails active_storage:install
$ rails db:migrate
Enter fullscreen mode Exit fullscreen mode

Uploading a file

All Active Storage upload need to be connected to a model. To tell rails "We'd like to have a method called avatar on this model, which is a file attachment" we use the method has_one_attached method like this:

class Post < ApplicationRecord
  has_one_attached :avatar

  validates :title, presence: true
end
Enter fullscreen mode Exit fullscreen mode

From there, we can pass a file object to that field & it'll save to the database.

Resizing an Image

The awesome thing about Active Storage, is we can create new versions of an image on the fly. This means Rails won't perform the resize until the user requests that image, and after the transformation is complete it will cache the results for future use.

The documentation is a little unclear as to what options as can passed into the variant method, but I found the arguments link to the methods found on the ImageProcessing::MiniMagick Documentation.

Here is a cheat sheet I put together for transforming images:

<!-- Change the format of the image -->
<%= image_tag @post.avatar.variant(format: :jpg) %>

<!-- Rotate the image 45° -->
<%= image_tag @post.avatar.variant(rotate: [45, background: '#0F0']) %>

<!-- Saver - compress the image -->
<%= image_tag @post.avatar.variant(saver: { quality: 10 }) %>

<!--
  resize_and_pad: Image will be resized to 500x500 while keeping the original aspect ratio.
  Any remaining space (e.g. if the image was originally 50x10, so will scale up to 500x100) will be filled in with the colour we pick in 'background'
  We use Gravity to define where the left over space will be, so "north" will anchor the original image at the top of the new resized image.
-->
<%= image_tag @post.avatar.variant(resize_and_pad: [500, 500, gravity: 'north', background: '#000']) %>

<!--
  Resizes the image to fill the specified dimensions while retaining the original aspect ratio.
  If necessary, will crop the image in the larger dimension.
-->
<%= image_tag @post.avatar.variant(resize_to_limit: [500, 500]) %>

<!--
  Resize the image to fit within the specified dimensions while retaining the aspect ratio of the original image.
-->
<%= image_tag @post.avatar.variant(resize_to_fill: [500, 500, gravity: 'north']) %>

<!--
  Resizes the image to fit within the specified dimensions while retaining the original aspect ratio.
  Will downsize the image if it's larger than the specified dimensions or upsize if it's smaller.
-->
<%= image_tag @post.avatar.variant(resize_to_fit: [500, 500]) %>
Enter fullscreen mode Exit fullscreen mode

References

Top comments (2)

Collapse
 
hoss3770 profile image
Hossam Khalifa • Edited

I don't knwo why I can not convert my image to avif formati with activestorage
Do you have any clue how to do this?

<%= image_tag @post.avatar.variant(format: :avif) %>
Enter fullscreen mode Exit fullscreen mode

does not work

Collapse
 
konnorrogers profile image
Konnor Rogers • Edited

I dont think symbols get converted to strings. I think this should work:

 <%= image_tag @post.avatar.variant(convert: "avif") %>
Enter fullscreen mode Exit fullscreen mode