dchuk/rails_ai_agents · Archived

active-storage-setup

Configures Active Storage for file uploads with variants and direct uploads. Use when adding file uploads, image attachments, document storage, generating thumbnails, or when user mentions Active Storage, file upload, attachments, or image processing.

First seen Feb 13, 2026

Installation

$ npx skills add dchuk/rails_ai_agents --skill active-storage-setup

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from dchuk/rails_ai_agents · top by installs.

npx skills add dchuk/rails_ai_agents

Browse all from dchuk/rails_ai_agents

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

License LICENSE
Default branch main
Status Archived

Skill metadata

Parsed from SKILL.md frontmatter.

Allowed toolsRead, Write, Edit, Bash, Glob, Grep

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 6,494 B
  • docs SUMMARY.md 279 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 2 installs

SKILL.md

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_processing

Configuration

# 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 = :amazon

Model 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
end

Multiple Attachments

class Event < ApplicationRecord
  has_many_attached :photos
  has_many_attached :documents
end

Validations

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
end

With activestoragevalidations 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 }
end

Image 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
end

Controller 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
end

Fixtures Setup

Place test files in test/fixtures/files/:

test/fixtures/files/
├── avatar.jpg
├── document.pdf
└── photo.png

Controller 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
end

Multiple Uploads

def event_params
  params.require(:event).permit(:name, photos: [], documents: [])
end

Forms

<%= 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_documents

Checklist

  • 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