Bard Attachment Field

An enhanced file upload field for Rails forms, powered by web components. Provides drag-and-drop uploads, image/video previews, and seamless ActiveStorage direct upload integration.

Features

  • Drag-and-drop file uploads
  • Image and video previews
  • Direct uploads to ActiveStorage
  • Multiple file support
  • Client-side validation (required, accepted types, max size)
  • Upload progress dialog
  • Persists attachments through server-side validation errors
  • Supports Rails 7.1, 7.2, 8.0, and 8.1

Installation

Add to your Gemfile:

gem "bard-attachment_field"

The engine ships a prebuilt input-attachment.js bundle and adds it to the Sprockets precompile list automatically. Load it as a module script in your layout:

<script type="module" src="<%= asset_path("input-attachment.js") %>"></script>

The model must declare an ActiveStorage attachment:

class Post < ApplicationRecord
  has_one_attached :image
  has_many_attached :images
end

Usage

In your form, use attachment_field just like any other form builder field. It automatically sets the form's encoding to multipart:

<%= form.attachment_field :image %>
<%= form.attachment_field :images, multiple: true %>

Options

Option Description
multiple: true Allow multiple files (use with has_many_attached).
accepts: "image" Restrict accepted file types. Comma-separated list of type prefixes, e.g. "image,video".
max: 5.megabytes Maximum file size.
required: true Require at least one file.
preview: false Disable image/video previews.
disabled: true Disable the field.
upload_dialog: false Disable the upload progress dialog shown during direct uploads.
directupload: "/path" Override the ActiveStorage direct upload URL (defaults to /rails/active_storage/direct_uploads).
<%= form.attachment_field :image, accepts: "image", max: 5.megabytes, required: true %>
<%= form.attachment_field :media, accepts: "image,video", multiple: true %>

Custom rendering

Pass a block to render your own children inside the <input-attachment> element instead of the default persisted-attachment markup. The block receives the resolved HTML options:

<%= form.attachment_field :image do |options| %>
  <!-- custom <attachment-file> markup -->
<% end %>

Development

This project has two parts: the Ruby gem and the Stencil web components in input-attachment/.

The web components use Bun:

cd input-attachment
bun install
bun run build   # builds app/assets/javascripts/input-attachment.js
bun run test    # JS component tests

The JavaScript bundle must be built before running the Ruby test suite, which is driven by Cucumber against a self-contained Rails app:

bundle exec cucumber features/

Multi-Rails testing uses Appraisal with the gemfiles in gemfiles/.

License

MIT