rails/rails
Active Storage
Active contributors: rafaelfranca, georgeclaghorn, byroot
Purpose
Active Storage attaches files to Active Record models and stores them on local disk or a cloud service (S3, GCS, Azure via a separate gem). It provides direct uploads, image transformation, audio/video transcoding, metadata extraction, and previews.
Source: activestorage/lib/active_storage/ plus activestorage/app/. ~3,900 lines of lib/ Ruby and a JavaScript direct-upload client.
Directory layout
activestorage/
├── app/
│ ├── controllers/active_storage/ # Blob, Direct upload, Disk service controllers
│ ├── jobs/active_storage/ # AnalyzeJob, MirrorJob, PurgeJob, TransformJob
│ ├── models/active_storage/ # Blob, Attachment, Variant, VariantRecord, Preview
│ ├── javascript/ # Direct upload JS client
│ └── assets/ # Stylesheets
├── config/
│ └── routes.rb # /rails/active_storage/* routes
├── db/migrate/ # active_storage_blobs, attachments, variant_records
├── lib/
│ └── active_storage/
│ ├── analyzer/ # Image, video, audio metadata extraction
│ ├── analyzer.rb
│ ├── attached/ # has_one_attached, has_many_attached
│ ├── attached.rb
│ ├── engine.rb
│ ├── errors.rb
│ ├── fixture_set.rb
│ ├── log_subscriber.rb
│ ├── previewer/ # PDF, Video → image preview
│ ├── previewer.rb
│ ├── reflection.rb
│ ├── service/ # Disk, S3, GCS, Mirror
│ ├── service.rb
│ ├── structured_event_subscriber.rb
│ └── transformers/ # ImageMagick, libvips, video
└── activestorage.gemspecKey abstractions
| Constant | File | Purpose |
|---|---|---|
ActiveStorage::Blob |
activestorage/app/models/active_storage/blob.rb |
One stored file plus metadata |
ActiveStorage::Attachment |
activestorage/app/models/active_storage/attachment.rb |
Join row tying a blob to a parent record |
ActiveStorage::Service |
activestorage/lib/active_storage/service.rb |
Base class for storage backends |
ActiveStorage::Service::DiskService |
activestorage/lib/active_storage/service/disk_service.rb |
Local filesystem backend |
ActiveStorage::Service::S3Service |
activestorage/lib/active_storage/service/s3_service.rb |
AWS S3 backend |
ActiveStorage::Service::GCSService |
activestorage/lib/active_storage/service/gcs_service.rb |
Google Cloud Storage backend |
ActiveStorage::Service::MirrorService |
activestorage/lib/active_storage/service/mirror_service.rb |
Wrap multiple services for replication |
ActiveStorage::Variant |
activestorage/app/models/active_storage/variant.rb |
Image transformation result |
ActiveStorage::Preview |
activestorage/app/models/active_storage/preview.rb |
Preview image (PDF, video) |
ActiveStorage::Analyzer |
activestorage/lib/active_storage/analyzer/ |
Extract dimensions, duration, etc. |
ActiveStorage::Previewer |
activestorage/lib/active_storage/previewer/ |
Generate preview image from non-image |
ActiveStorage::Transformers::* |
activestorage/lib/active_storage/transformers/ |
ImageMagick / libvips / ffmpeg backends |
How attachment works
class User < ApplicationRecord
has_one_attached :avatar
has_many_attached :photos
endImplementation lives in activestorage/lib/active_storage/attached/:
model.rb— thehas_one_attachedandhas_many_attachedmacros.one.rb/many.rb— proxies returned byuser.avatar/user.photos.changes/— pending attach / detach operations bundled with the parent record's lifecycle.
When you call user.avatar.attach(file), an ActiveStorage::Attachment row is created pointing to a new (or existing) ActiveStorage::Blob. The blob has a service_name, key, byte_size, checksum, content_type, and metadata.
Storage services
activestorage/lib/active_storage/service/:
DiskService— writes underRails.root.join("storage"). Used in dev/test by default.S3Service— uses theaws-sdk-s3gem (declared in the host app'sGemfile, not Active Storage's gemspec).GCSService— usesgoogle-cloud-storage.MirrorService— composite that mirrors writes to multiple services and reads from a primary. Useful during a storage migration.- Azure was extracted into the separate
azure-storage-blobgem in 7.x.
Each service implements:
upload(key, io, ...)/download(key, &block)/delete(key)/exist?(key)url_for_direct_upload(key, ...)— pre-signed upload URLurl(key, ...)— pre-signed download URLheaders_for_direct_upload(key, ...)— required headers for the direct upload
Direct uploads
The direct_uploads_controller (activestorage/app/controllers/active_storage/direct_uploads_controller.rb) issues a pre-signed URL plus headers; the JS client uploads directly to S3/GCS/disk without bouncing through the Rails server. Implementation in activestorage/app/javascript/active_storage/direct_upload.js.
Variants and previews
ActiveStorage::Variant represents a derived image:
user.avatar.variant(resize_to_limit: [100, 100])The transformation is described by an ActiveStorage::Transformer (activestorage/lib/active_storage/transformers/image_processing_transformer.rb). The image_processing gem is the supported backend, which itself wraps mini_magick (ImageMagick) or ruby-vips (libvips).
Previews handle non-image files: PDFs (Poppler), videos (ffmpeg). Previewers live in activestorage/lib/active_storage/previewer/.
Analyzers
activestorage/lib/active_storage/analyzer/:
null_analyzer.rbimage_analyzer.rb(withvips.rbandimage_magick.rbflavors)audio_analyzer.rbvideo_analyzer.rb
When a blob is uploaded, an AnalyzeJob runs through analyzers in order; the first matching one writes its findings into blob.metadata.
Background jobs
activestorage/app/jobs/active_storage/:
analyze_job.rb— runs analyzers after upload.mirror_job.rb— copies a blob to mirrored services.purge_job.rb— cleans up after a record is destroyed.transform_job.rb— pre-generates variant images.
Engine
activestorage/lib/active_storage/engine.rb is a Rails::Engine that:
- Mounts
/rails/active_storage/routes (representations, blobs, direct uploads). - Runs the migration to create
active_storage_blobs,active_storage_attachments, andactive_storage_variant_records. - Wires
has_one_attached/has_many_attachedinto Active Record via a lazy load hook.
Integration points
- Active Record — host records, attachment join model.
- Active Job — analyses, transformations, purges.
- Action Text — embedded blobs are Active Storage attachments.
- Action Mailbox — raw inbound emails are stored as blobs.
- Action Pack — controllers under
/rails/active_storage/.
Entry points for modification
- Adding a service: subclass
ActiveStorage::Serviceand implement the upload/download/url methods. Tests underactivestorage/test/service/<name>_service_test.rb. - Adding an analyzer: subclass
ActiveStorage::Analyzer, register viaconfig.active_storage.analyzers. - Adding a previewer: subclass
ActiveStorage::Previewer, register viaconfig.active_storage.previewers. - Modifying the direct upload protocol: changes to the controller, the JS client, and the service-specific
headers_for_direct_uploadmust stay in sync.
Related pages
- packages/active-record — host records.
- packages/active-job — background work.
- packages/action-text — embeds Active Storage attachments inline.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.