Skip to content

rigor-activestorage

Walks ActiveRecord model files for has_one_attached / has_many_attached macros and types the attachment accessors they generate, so navigating an attachment resolves through ActiveStorage’s own RBS surface instead of falling to the untyped envelope. It reads source only — no Rails runtime dependency.

It ships bundled in rigortype. Activate it under plugins::

plugins:
- rigor-activestorage
class User < ApplicationRecord
has_one_attached :avatar
has_many_attached :photos
end
user = User.find(1)
user.avatar # Nominal[ActiveStorage::Attached::One]
user.avatar.attached? # resolves through ActiveStorage's RBS
user.photos # Nominal[ActiveStorage::Attached::Many]
MacroAccessorContributed type
has_one_attached :avataruser.avatarNominal[ActiveStorage::Attached::One]
has_many_attached :photosuser.photosNominal[ActiveStorage::Attached::Many]

Setters (user.avatar = …) and attachment-name calls with arguments decline — those are covered by ActiveStorage’s own RBS.

RuleSeverityWhen
plugin.activestorage.attachment-callinfoa recognised model.attachment_name call surfaces; confirms the model → attachment mapping
plugin.activestorage.load-errorwarningdiscovery failed (e.g. the model directory is inaccessible under the IoBoundary trust policy)

No :error diagnostics in this slice — the value is the return-type contribution; an “unknown attachment name” rule is a future slice.

plugins:
- gem: rigor-activestorage
config:
model_search_paths: ["app/models"] # default

The plugin discovers model files independently, so it works stand-alone. When rigor-activerecord is also active the two coexist (each contributes its own per-call return type and the contribution merger reconciles); the :model_index dependency is declared optional, reserved for a future slice that would restrict attachment recognition to discovered AR classes.

The discovery pass, the AttachmentIndex, and the contract surfaces this plugin exercises are in the plugin’s README. To write a plugin, see examples/ and the rigor-plugin-author skill.

© 2026 TypedDuck. Licensed under CC BY-SA 4.0.