Files
The Files field is similar to File and enables you to upload multiple files at once using the same easy-to-use Active Storage implementation.
# app/avo/resources/project.rb
class Avo::Resources::Project < Avo::BaseResource
def fields
field :documents, as: :files
end
endBy default, Avo shows a file count on the index and a grid of attachments on the show and edit pages, with a grid/list switcher and filenames. Images open in a lightbox on the show page; direct uploads are off and the file picker has no file-type restriction.
Set up multiple attachments
Back the field with an Active Storage association:
# app/models/project.rb
class Project < ApplicationRecord
has_many_attached :documents
endUploads are added to the existing attachments when the record saves. A failed validation does not attach the newly selected files.
WARNING
Require activestorage and image_processing in your Gemfile.
# Gemfile
gem "activestorage"
gem "image_processing"Control which files users upload
Use accept to filter the file picker. It is a browser hint, not server-side validation; validate attachments in your model if the restriction must be enforced.
# app/avo/resources/project.rb
field :documents, as: :files, accept: "image/*,application/pdf"For large files, enable direct_upload to upload directly to your storage service rather than sending the file through your application server. Configure Active Storage direct uploads for your service first.
# app/avo/resources/project.rb
field :documents, as: :files, direct_upload: trueChoose where uploads are stored
Active Storage stores every upload under a random key. Set key to choose the key yourself, so the files in your bucket can be found by name. Since avo >= v4.4.4
# app/avo/resources/project.rb
field :documents,
as: :files,
key: -> { "projects/#{SecureRandom.base36(8)}/#{ActiveStorage::Filename.new(file.original_filename).sanitized}" }The block gets the record, the resource, the field and the uploaded file. The block runs once per file, so each file needs its own key. Two files of one upload with the same key are refused. If it returns nil or an empty string, the file keeps a random key.
WARNING
- Keys are unique. When a key is already taken, the form shows "has already been taken" on the field and nothing is saved. Replacing a file with one of the same name counts, because the old file still exists at that moment. Put something that changes per upload in the key, like the random segment above.
- New records have no id yet. On the New page
record.idandrecord.to_paramarenil, so don't build the key from them. file.original_filenamecomes from the browser. Sanitize it before it goes into a key, as above.- Only files uploaded through the form get the key. With
direct_upload, or a file picked from the Media Library, the file is already stored when the form is sent, so it keeps its key.
Choose how attachments appear
Set view_type to start with a list instead of a grid.
To remove the switcher, add hide_view_type_switcher.
# app/avo/resources/project.rb
field :documents, as: :files, view_type: :list, hide_view_type_switcher: trueFor a cleaner image grid, hide captions with display_filename. List rows still show their filenames.
# app/avo/resources/project.rb
field :documents, as: :files, display_filename: falsePreview images in place
On the show page, clicking an image opens an in-page lightbox. Use the arrow buttons or arrow keys to cycle through the field's images, and press Esc or click outside the image to close it. The lightbox links to the original file in a new tab when downloads are authorized. Non-image files retain their players and download controls.
Set lightbox to false to leave image thumbnails non-interactive. Form thumbnails never open the lightbox.
# app/avo/resources/project.rb
field :documents, as: :files, lightbox: falseDisplay images from phones and design tools
Avo serves browser-friendly images such as PNG, JPEG, GIF, WebP, and AVIF directly from storage. For variable attachments with content types image/heic, image/heif, image/tiff, or image/vnd.adobe.photoshop, it uses an Active Storage variant rendered as PNG. This lets browsers without native support display them too.
WARNING
Conversion needs an image processor installed: libvips built with libheif, or ImageMagick with the HEIC delegate for HEIC images. Without a suitable processor the variant cannot be processed. See Active Storage's requirements.
Authorize uploads, downloads, and deletion
Ensure your model's Pundit policy permits upload_documents?, download_documents?, and delete_documents? for the corresponding controls to appear. Replace documents with your field's ID.
See Attachment pundit policies for policy examples.
Configure shared field behavior
For labels, visibility, read-only behavior, and other options shared by all fields, see Common field options. For the attachment-specific contracts, see the Files API reference.