module ActiveStorage::Blob::Representable
def create_preview_image_later(variations) # :nodoc:
def create_preview_image_later(variations) # :nodoc: ActiveStorage::PreviewImageJob.perform_later(self, variations) if representable? end
def default_variant_format
def default_variant_format if web_image? format || :png else :png end end
def default_variant_transformations
def default_variant_transformations { format: default_variant_format } end
def format
def format if filename.extension.present? && Marcel::MimeType.for(extension: filename.extension) == content_type filename.extension else Marcel::Magic.new(content_type.to_s).extensions.first end end
def preprocessed(transformations) # :nodoc:
def preprocessed(transformations) # :nodoc: ActiveStorage::TransformJob.perform_later(self, transformations) if representable? end
def preview(transformations)
This method raises ActiveStorage::UnpreviewableError if no previewer accepts the receiving blob. To determine
<%= image_tag video.preview(resize_to_limit: [100, 100]) %>
how to use the built-in version:
Active Storage provides one, but you may want to create your own (for example, if you need authentication). Here’s
Avoid processing previews synchronously in views. Instead, link to a controller action that processes them on demand.
blob.preview(resize_to_limit: [100, 100]).processed.url
extracts the first frame from a video and the PDF previewer extracts the first page from a PDF document.
from a non-image blob. Active Storage comes with built-in previewers for videos and PDF documents. The video previewer
Returns an ActiveStorage::Preview instance with the set of +transformations+ provided. A preview is an image generated
def preview(transformations) if previewable? ActiveStorage::Preview.new(self, transformations) else raise ActiveStorage::UnpreviewableError end end
def preview_image_needed_before_processing_variants? # :nodoc:
def preview_image_needed_before_processing_variants? # :nodoc: previewable? && !preview_image.attached? end
def previewable?
def previewable? ActiveStorage.previewers.any? { |klass| klass.accept?(self) } end
def representable?
def representable? variable? || previewable? end
def representation(transformations)
ActiveStorage::Blob#representable? to determine whether a blob is representable.
Raises ActiveStorage::UnrepresentableError if the receiving blob is neither variable nor previewable. Call
blob.representation(resize_to_limit: [100, 100]).processed.url
Returns an ActiveStorage::Preview for a previewable blob or an ActiveStorage::Variant for a variable image blob.
def representation(transformations) case when previewable? preview transformations when variable? variant transformations else raise ActiveStorage::UnrepresentableError end end
def variable?
Returns true if the variant processor can transform the blob (its content
def variable? ActiveStorage.variable_content_types.include?(content_type) end
def variant(transformations)
saver: { subsample_mode: "on", strip: true, interlace: true, quality: 80 }) %>
<%= image_tag user.avatar.variant(resize_to_limit: [100, 100], format: :jpeg,
sampling_factor: "4:2:0", strip: true, interlace: "JPEG", colorspace: "sRGB", quality: 80) %>
<%= image_tag user.avatar.variant(resize_to_limit: [100, 100], format: :jpeg,
need to update processor-specific options:
If migrating an existing application between MiniMagick and Vips, you will
<%= image_tag user.avatar.variant(resize_to_fill: [100, 100, { crop: :centre }]) %>
processor-specific values which can be passed as a trailing hash:
Some options, including those listed above, can accept additional
user.avatar.variant(rotate: 90)
Rotates the image by the specified angle.
[+:rotate+]
user.avatar.variant(crop: [20, 50, 300, 300])
and height of the area to extract.
top edges of area to extract, while the last two arguments are the width
Extracts an area from an image. The first two arguments are the left and
[+:crop+]
user.avatar.variant(resize_and_pad: [100, 100])
transparent color if source image has alpha channel, black otherwise.
the original aspect ratio. If necessary, will pad the remaining area with
Resizes the image to fit within the specified dimensions while retaining
[+:resize_and_pad+]
user.avatar.variant(resize_to_fill: [100, 100])
dimension.
original aspect ratio. If necessary, will crop the image in the larger
Resizes the image to fill the specified dimensions while retaining the
[+:resize_to_fill+]
user.avatar.variant(resize_to_fit: [100, 100])
specified dimensions or upsize if it's smaller.
the original aspect ratio. Will downsize the image if it's larger than the
Resizes the image to fit within the specified dimensions while retaining
[+:resize_to_fit+]
user.avatar.variant(resize_to_limit: [100, 100])
the specified dimensions.
the original aspect ratio. Will only resize the image if it's larger than
Downsizes the image to fit within the specified dimensions while retaining
[+:resize_to_limit+]
However, both variant processors support the following options:
{MiniMagick}[https://github.com/janko/image_processing/blob/master/doc/minimagick.md].
{Vips}[https://github.com/janko/image_processing/blob/master/doc/vips.md] or
and depend on which variant processor you are using:
Options are defined by the {image_processing gem}[https://github.com/janko/image_processing],
==== Options
ActiveStorage::Blob#variable?.
transform the blob. To determine whether a blob is variable, call
Raises ActiveStorage::InvariableError if the variant processor cannot
can then produce on-demand.
This will create a URL for that specific blob with that specific variant, which the ActiveStorage::RepresentationsController
<%= image_tag Current.user.avatar.variant(resize_to_limit: [100, 100]) %>
specific variant that can be created by a controller on-demand. Like so:
Frequently, though, you don't actually want to transform the variant right away. But rather simply refer to a
Then it'll upload said variant to the service according to a derivative key of the blob and the transformations.
This will create and process a variant of the avatar blob that's constrained to a height and width of 100px.
avatar.variant(resize_to_limit: [100, 100]).processed.url
This is only relevant for image files, and it allows any image to be transformed for size, colors, and the like. Example:
Returns an ActiveStorage::Variant or ActiveStorage::VariantWithRecord instance with the set of +transformations+ provided.
def variant(transformations) if variable? variant_class.new(self, ActiveStorage::Variation.wrap(transformations).default_to(default_variant_transformations)) else raise ActiveStorage::InvariableError end end
def variant_class
def variant_class ActiveStorage.track_variants ? ActiveStorage::VariantWithRecord : ActiveStorage::Variant end