How store multiple sizes of same image with ActiveStorage?

Viewed 709

I have image uploads working like so

#user.rb
has_many_attached :images
<%= f.label :user_images %>
<%= f.file_field :user_images, multiple: true %>

I know how to resize images in the view e.g. image_tag(user.images.first, {size: "300x300"})

The problem with this approach is that it sends the full-size image to the view, then resizes it using CSS, so it can cause a lot of unnecessary use of the network. So I prefer to store multiple sizes when the user uploads the image, then serve the appropriate sized image as required.

How do I do this?

2 Answers

A partial answer on how to resize on upload from code in a youtube comment (top/pinned comment here):

class Post < ApplicationRecord
  has_one_attached :image
  after_create :scale_image

  def scale_image
    resized_image = MiniMagick::Image.read(image.download)
    resized_image.resize("300x300!")

    image.attach(
      io: File.open(resized_image.path),
      filename: image.filename,
      content_type: image.content_type)
  end

end

The comment by Max is correct. You can define a variant and force it to be processed without being in a template:

When you do want to actually produce the variant needed, call processed. This will check that the variant has already been processed and uploaded to the service, and, if so, just return that. Otherwise it will perform the transformations, upload the variant to the service, and return itself again.

In your callback or anywhere else:

user.images.first.variant(resize_to_limit: [300, 300]).processed
Related