Repository: rails/rails
File: activestorage/app/models/active_storage/blob/representable.rb (Ruby)

Code before:
module ActiveStorage::Blob::Representable
  extend ActiveSupport::Concern

  included do
    has_one_attached :preview_image
  end

  # Returns an ActiveStorage::Variant instance with the set of +transformations+ provided. This is only relevant for image
  # files, and it allows any image to be transformed for size, colors, and the like. Example:
  #
  #   avatar.variant(resize_to_limit: [100, 100]).processed.service_url
  #
  # This will create and process a variant of the avatar blob that's constrained to a height and width of 100px.
  # Then it'll upload said variant to the service according to a derivative key of the blob and the transformations.
  #
  # Frequently, though, you don't actually want to transform the variant right away. But rather simply refer to a
  # specific variant that can be created by a controller on-demand. Like so:
  #
  #   <%= image_tag Current.user.avatar.variant(resize_to_limit: [100, 100]) %>
  #
  # This will create a URL for that specific blob with that specific variant, which the ActiveStorage::RepresentationsController
  # can then produce on-demand.
  #
  # Raises ActiveStorage::InvariableError if ImageMagick cannot transform the blob. To determine whether a blob is
  # variable, call ActiveStorage::Blob#variable?.
  def variant(transformations, delivery_method = nil)
    if variable?
      ActiveStorage::Variant.new(self, transformations, delivery_method)
    else
      raise ActiveStorage::InvariableError
    end
  end

  # Returns true if ImageMagick can transform the blob (its content type is in +ActiveStorage.variable_content_types+).
  def variable?
    ActiveStorage.variable_content_types.include?(content_type)
  end


  # Returns an ActiveStorage::Preview instance with the set of +transformations+ provided. A preview is an image generated
  # from a non-image blob. Active Storage comes with built-in previewers for videos and PDF documents. The video previewer
  # extracts the first frame from a video and the PDF previewer extracts the first page from a PDF document.
  #
  #   blob.preview(resize_to_limit: [100, 100]).processed.service_url
  #
  # Avoid processing previews synchronously in views. Instead, link to a controller action that processes them on demand.
  # Active Storage provides one, but you may want to create your own (for example, if you need authentication). Here’s
  # how to use the built-in version:
  #
  #   <%= image_tag video.preview(resize_to_limit: [100, 100]) %>
  #

Review comment (suggestion):
Not liking this. It's a smell that the delivery method has to get passed around like this. Whatever the final return is, there should be a way to call a URL method on it that specifies the delivery method. Not when creating the variant or the preview.

Code after:
module ActiveStorage::Blob::Representable
  extend ActiveSupport::Concern

  included do
    has_many :variant_records, class_name: "ActiveStorage::VariantRecord", dependent: false
    before_destroy { variant_records.destroy_all if ActiveStorage.track_variants }

    has_one_attached :preview_image
  end

  # Returns an ActiveStorage::Variant instance with the set of +transformations+ provided. This is only relevant for image
  # files, and it allows any image to be transformed for size, colors, and the like. Example:
  #
  #   avatar.variant(resize_to_limit: [100, 100]).processed.url
  #
  # This will create and process a variant of the avatar blob that's constrained to a height and width of 100px.
  # Then it'll upload said variant to the service according to a derivative key of the blob and the transformations.
  #
  # Frequently, though, you don't actually want to transform the variant right away. But rather simply refer to a
  # specific variant that can be created by a controller on-demand. Like so:
  #
  #   <%= image_tag Current.user.avatar.variant(resize_to_limit: [100, 100]) %>
  #
  # This will create a URL for that specific blob with that specific variant, which the ActiveStorage::RepresentationsController
  # can then produce on-demand.
  #
  # Raises ActiveStorage::InvariableError if ImageMagick cannot transform the blob. To determine whether a blob is
  # variable, call ActiveStorage::Blob#variable?.
  def variant(transformations)
    if variable?
      variant_class.new(self, transformations)
    else
      raise ActiveStorage::InvariableError
    end
  end

  # Returns true if ImageMagick can transform the blob (its content type is in +ActiveStorage.variable_content_types+).
  def variable?
    ActiveStorage.variable_content_types.include?(content_type)
  end


  # Returns an ActiveStorage::Preview instance with the set of +transformations+ provided. A preview is an image generated
  # from a non-image blob. Active Storage comes with built-in previewers for videos and PDF documents. The video previewer
  # extracts the first frame from a video and the PDF previewer extracts the first page from a PDF document.
  #
  #   blob.preview(resize_to_limit: [100, 100]).processed.url
  #
  # Avoid processing previews synchronously in views. Instead, link to a controller action that processes them on demand.
  # Active Storage provides one, but you may want to create your own (for example, if you need authentication). Here’s
  # how to use the built-in version: