Skip to Content Skip to Search

Active Storage Attachment

Attachments associate records with blobs. Usually that’s a one record-many blobs relationship, but it is possible to associate many different records with the same blob. A foreign-key constraint on the attachments table prevents blobs from being purged if they’re still attached to any records.

Attachments also have access to all methods from ActiveStorage::Blob.

If you wish to preload attachments or blobs, you can use these scopes:

# preloads attachments, their corresponding blobs, and variant records (if using `ActiveStorage.track_variants`)
User.all.with_attached_avatars

# preloads blobs and variant records (if using `ActiveStorage.track_variants`)
User.first.avatars.with_all_variant_records
Methods
B
P
R
U
V
W

Attributes

[RW] immediate_variants_processed

Set to true when immediate variants have been processed from local io, so create_variants knows to skip them.

[RW] pending_upload

Set to true for fresh uploads (io provided), false for existing blobs. Used to determine whether to run :upload callbacks in after_create_commit.

Class Public methods

with_all_variant_records

Eager load all variant records on an attachment at once.

User.first.avatars.with_all_variant_records
# File activestorage/app/models/active_storage/attachment.rb, line 59
scope :with_all_variant_records, -> { includes(blob: {
  variant_records: { image_attachment: :blob },
  preview_image_attachment: { blob: { variant_records: { image_attachment: :blob } } }

Instance Public methods

blob

Returns the associated ActiveStorage::Blob.

# File activestorage/app/models/active_storage/attachment.rb, line 45
belongs_to :blob, class_name: "ActiveStorage::Blob", autosave: true, inverse_of: :attachments

preview(transformations)

Returns an ActiveStorage::Preview instance for the attachment with the set of transformations provided. Example:

video.preview(resize_to_limit: [100, 100]).processed.url

or if you are using pre-defined variants:

video.preview(:thumb).processed.url

See ActiveStorage::Blob::Representable#preview for more information.

Raises an ArgumentError if transformations is a Symbol which is an unknown pre-defined variant of the attachment.

# File activestorage/app/models/active_storage/attachment.rb, line 140
def preview(transformations)
  transformations = transformations_by_name(transformations)
  blob.preview(transformations)
end

purge()

Synchronously deletes the attachment and purges the blob.

# File activestorage/app/models/active_storage/attachment.rb, line 90
def purge
  transaction do
    delete
    record.touch if record&.persisted?
  end
  blob&.purge
end

purge_later()

Deletes the attachment and enqueues a background job to purge the blob.

# File activestorage/app/models/active_storage/attachment.rb, line 99
def purge_later
  transaction do
    delete
    record.touch if record&.persisted?
  end
  blob&.purge_later
end

record

Returns the associated record.

# File activestorage/app/models/active_storage/attachment.rb, line 39
belongs_to :record, polymorphic: true, touch: ActiveStorage.touch_attachment_records

representation(transformations)

Returns an ActiveStorage::Preview or an ActiveStorage::Variant for the attachment with set of transformations provided. Example:

avatar.representation(resize_to_limit: [100, 100]).processed.url

or if you are using pre-defined variants:

avatar.representation(:thumb).processed.url

See ActiveStorage::Blob::Representable#representation for more information.

Raises an ArgumentError if transformations is a Symbol which is an unknown pre-defined variant of the attachment.

# File activestorage/app/models/active_storage/attachment.rb, line 159
def representation(transformations)
  transformations = transformations_by_name(transformations)
  blob.representation(transformations)
end

uploaded(io:)

Called by Attached::Changes::CreateOne to handle the upload workflow for fresh uploads. Processes immediate variants and analyzes from the local io (avoiding a download round-trip), uploads the blob, then runs the :upload callbacks.

For existing blob attachments, the :upload callbacks are run via after_create_commit instead.

# File activestorage/app/models/active_storage/attachment.rb, line 71
def uploaded(io:)
  blob.local_io = io

  process_immediate_variants_from_io(io)
  analyze_blob_from_io(io)

  io.rewind if io.respond_to?(:rewind)
  blob.upload_without_unfurling(io)

  # Persist analysis metadata if the blob was already saved (happens when
  # upload runs in after_commit, after the blob was saved via autosave).
  blob.save! if blob.persisted? && blob.metadata_changed?

  run_upload_callbacks
ensure
  blob.local_io = nil
end

variant(transformations)

Returns an ActiveStorage::Variant or ActiveStorage::VariantWithRecord instance for the attachment with the set of transformations provided. Example:

avatar.variant(resize_to_limit: [100, 100]).processed.url

or if you are using pre-defined variants:

avatar.variant(:thumb).processed.url

See ActiveStorage::Blob::Representable#variant for more information.

Raises an ArgumentError if transformations is a Symbol which is an unknown pre-defined variant of the attachment.

# File activestorage/app/models/active_storage/attachment.rb, line 121
def variant(transformations)
  transformations = transformations_by_name(transformations)
  blob.variant(transformations)
end