16

I have an Active Storage image variant e.g.

<%= image_tag model.logo_image.variant(resize_to_fit: [300, 200]) %>

I'm trying to get the width and height values of this variant (since they are unknown) for use in the width and height HTML attributes.

I expected them to be here:

model.logo_image.variant(resize_to_fit: [300, 200]).processed.blob.metadata

But this gives me the metadata of the original file not the resized variant e.g.

{"identified"=>true, "width"=>800, "height"=>174, "analyzed"=>true}

How do I get the dimensions of an Active Storage variant?

Alec Rust
  • 10,532
  • 12
  • 48
  • 63
  • It seems to be regarded as a feature by rails maintainers. See: https://github.com/rails/rails/issues/34263 – khiav reoy Oct 05 '20 at 17:02

1 Answers1

8

With Rails 6.1, finally all Variations are stored in a new model/database table and each variation with a Blob. Try upgrading, if this feature is relevant for you.

Very deep into the object, you can find then the variation blob, and thus the metadata, though!

Try:

model.logo_image.
 variant(resize_to_fit: [300, 200]).
 processed.send(:record).image.blob.metadata

It does not work the first time though, when called first time, it has no width/height, because the AnalyzeJob will run asynchronously, and it will add the width/height "later", depending on your queue setup.

Maybe add a helper_method that creates the image with width, height if available:

module ApplicationHelper
  def image_tag_for_attachment_with_dimensions(variant, opts = {})
    if variant.processed?
      metadata = variant.processed.send(:record).image.blob.metadata
      if metadata['width']
        opts[:width] = metadata['width']
        opts[:height] = metadata['height']
      end
    end
    image_tag variant, opts
  end
end

# usage: 
= image_tag_for_attachment_with_dimensions model.logo_image.variant(resize_to_fit: [300, 200])
Alec Rust
  • 10,532
  • 12
  • 48
  • 63
stwienert
  • 3,402
  • 24
  • 28
  • @AlecRust no problem! Could you accept the answer then ;)? – stwienert Apr 23 '21 at 21:34
  • 1
    Answer accepted I've made a couple edits. I assume this metadata is only now available in Rails 6.1 due to variant being tracked in database, as I looked everywhere on 6.0 and it wasn't present. – Alec Rust Apr 25 '21 at 13:46
  • The `variant.processed.send(:record).image.blob.metadata` chain can be shortened to `variant.processed.send(:record).image.metadata`, since I believe a lot of the public methods of `blob` is delegated in `image`. – Viet Sep 01 '21 at 17:01
  • 1
    This no longer works with 6.1.4, raising: `undefined method 'record' for #` – JP Silvashy Dec 30 '21 at 21:44
  • Careful, while this is good for image dimensions, this strategy will give the file size (using byte_size) of the blob, which is the original image not the variant. – Ivan Raszl Jun 09 '23 at 14:53