
Active Storage Setup
- 2 installs
- Updated February 9, 2026
- dchuk/rails_ai_agents
Configures Active Storage in Rails 8 for file uploads with variants, direct uploads, and cloud or local disk storage.
About
Sets up Active Storage for file uploads, image attachments, and thumbnail generation in Rails 8. A developer uses it when adding attachments, document storage, or image processing to an app.
- Cloud storage (S3, GCS, Azure) or local disk
- Variants, direct uploads, and image processing
Active Storage Setup by the numbers
- 2 all-time installs (skills.sh)
- Ranked #3,765 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Jul 29, 2026 (Skillselion catalog sync)
npx skills add https://github.com/dchuk/rails_ai_agents --skill active-storage-setupAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 2 |
|---|---|
| Last updated | February 9, 2026 |
| Repository | dchuk/rails_ai_agents ↗ |
What it does
Configures Active Storage in Rails 8 for file uploads with variants, direct uploads, and cloud or local disk storage.
Files
Active Storage Setup for Rails 8
Overview
Active Storage handles file uploads in Rails:
- Cloud storage (S3, GCS, Azure) or local disk
- Image variants (thumbnails, resizing)
- Direct uploads from browser
- Polymorphic attachments
Quick Start
bin/rails active_storage:install
bin/rails db:migrate
bundle add image_processingConfiguration
# config/storage.yml
local:
service: Disk
root: <%= Rails.root.join("storage") %>
test:
service: Disk
root: <%= Rails.root.join("tmp/storage") %>
amazon:
service: S3
access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
region: eu-west-1
bucket: <%= Rails.application.credentials.dig(:aws, :bucket) %># config/environments/development.rb
config.active_storage.service = :local
# config/environments/production.rb
config.active_storage.service = :amazonModel Attachments
Single Attachment
class User < ApplicationRecord
has_one_attached :avatar do |attachable|
attachable.variant :thumb, resize_to_limit: [100, 100]
attachable.variant :medium, resize_to_limit: [300, 300]
end
endMultiple Attachments
class Event < ApplicationRecord
has_many_attached :photos
has_many_attached :documents
endValidations
Manual Validation
class User < ApplicationRecord
has_one_attached :avatar
validate :acceptable_avatar
private
def acceptable_avatar
return unless avatar.attached?
unless avatar.blob.byte_size <= 5.megabytes
errors.add(:avatar, "is too large (max 5MB)")
end
acceptable_types = ["image/jpeg", "image/png", "image/webp"]
unless acceptable_types.include?(avatar.content_type)
errors.add(:avatar, "must be a JPEG, PNG, or WebP")
end
end
endWith active_storage_validations Gem
gem "active_storage_validations"
class User < ApplicationRecord
has_one_attached :avatar
validates :avatar,
content_type: ["image/png", "image/jpeg", "image/webp"],
size: { less_than: 5.megabytes }
endImage Variants
# Resize to fit (maintains aspect ratio)
resize_to_limit: [300, 300]
# Resize and crop to exact dimensions
resize_to_fill: [300, 300]
# With format conversion
resize_to_limit: [300, 300], format: :webp, saver: { quality: 80 }Using in Views
<% if user.avatar.attached? %>
<%= image_tag user.avatar.variant(:thumb), alt: user.name %>
<% else %>
<%= image_tag "default-avatar.png", alt: "Default" %>
<% end %>Testing Attachments (Minitest)
Model Test
# test/models/user_test.rb
require "test_helper"
class UserAttachmentTest < ActiveSupport::TestCase
setup do
@user = users(:one)
end
test "attaches an avatar" do
@user.avatar.attach(
io: File.open(Rails.root.join("test/fixtures/files/avatar.jpg")),
filename: "avatar.jpg",
content_type: "image/jpeg"
)
assert @user.avatar.attached?
end
test "rejects oversized avatar" do
@user.avatar.attach(
io: StringIO.new("x" * 6.megabytes),
filename: "large.jpg",
content_type: "image/jpeg"
)
assert_not @user.valid?
assert_includes @user.errors[:avatar], "is too large (max 5MB)"
end
test "rejects invalid content type" do
@user.avatar.attach(
io: File.open(Rails.root.join("test/fixtures/files/document.pdf")),
filename: "doc.pdf",
content_type: "application/pdf"
)
assert_not @user.valid?
assert @user.errors[:avatar].any?
end
endController Test
# test/controllers/users_controller_test.rb
require "test_helper"
class UsersUploadTest < ActionDispatch::IntegrationTest
setup do
@user = users(:one)
sign_in @user
end
test "uploads avatar" do
avatar = fixture_file_upload("avatar.jpg", "image/jpeg")
patch user_path(@user), params: { user: { avatar: avatar } }
assert @user.reload.avatar.attached?
end
test "removes avatar" do
@user.avatar.attach(
io: File.open(Rails.root.join("test/fixtures/files/avatar.jpg")),
filename: "avatar.jpg",
content_type: "image/jpeg"
)
delete remove_avatar_user_path(@user)
assert_not @user.reload.avatar.attached?
end
endFixtures Setup
Place test files in test/fixtures/files/:
test/fixtures/files/
├── avatar.jpg
├── document.pdf
└── photo.pngController Handling
class UsersController < ApplicationController
def update
if @user.update(user_params)
redirect_to @user, notice: "Profile updated"
else
render :edit, status: :unprocessable_entity
end
end
def remove_avatar
@user.avatar.purge
redirect_to edit_user_path(@user), notice: "Avatar removed"
end
private
def user_params
params.require(:user).permit(:name, :email, :avatar)
end
endMultiple Uploads
def event_params
params.require(:event).permit(:name, photos: [], documents: [])
endForms
<%= form_with model: @user do |f| %>
<div>
<%= f.label :avatar %>
<%= f.file_field :avatar, accept: "image/png,image/jpeg,image/webp" %>
<% if @user.avatar.attached? %>
<%= image_tag @user.avatar.variant(:thumb), class: "rounded mt-2" %>
<% end %>
</div>
<%= f.submit %>
<% end %>Direct Uploads
// app/javascript/application.js
import * as ActiveStorage from "@rails/activestorage"
ActiveStorage.start()<%= f.file_field :photos, multiple: true, direct_upload: true %>Performance Tips
# Prevent N+1 on attachments
User.with_attached_avatar.limit(10)
# Multiple attachments
Event.with_attached_photos.with_attached_documentsChecklist
- [ ] Active Storage installed and migrated
- [ ] Storage service configured
- [ ] Image processing gem added
- [ ] Attachment added to model
- [ ] Validations added (type, size)
- [ ] Variants defined
- [ ] Controller permits attachment params
- [ ] Tests written for attachments
- [ ] All tests GREEN
Related skills
Backend & APIsbackend