Module: Plutonium::Wizard::Attachments
- Defined in:
- lib/plutonium/wizard/attachments.rb
Overview
Bridges a wizard's staged attachment value to the displayable attachment the
Uppy input and Display::Components::Attachment render — model-free and
backend-agnostic, for a bare attribute :photo, :string + input :photo, as: :uppy, direct_upload: true field (no using: model needed).
A wizard stages plain strings, so an attachment field holds its backend's own direct-upload token: ActiveStorage's signed_id (an opaque signed string) or active_shrine/Shrine's cached-file data (a JSON object). Those are the only two shapes, and they're distinguishable — a Shrine token parses as JSON, an AS signed_id doesn't — so we revive each through its own backend with no model and no per-field configuration.
Resolution is display-only: staging and execute (which assigns the token
straight to a model attachment — both AS and active_shrine accept it) never
call it. The two backends' native objects answer DIFFERENT method names
(filename/content_type vs original_filename/mime_type), so a resolved
token is wrapped in Resolved, a uniform view exposing exactly what the
display + preview components call. See the wizard-attachments design spec.
Defined Under Namespace
Classes: Resolved
Class Method Summary collapse
-
.attachment_backend ⇒ Object
The default server-side staging backend: the configured one, else auto-detected (active_shrine loaded → Shrine, else ActiveStorage).
-
.field?(input_options) ⇒ Boolean
Whether a step input renders as an attachment (its
as:is a file alias), so its staged token should be resolved for display. -
.resolve(value) ⇒ Array<Resolved>
Resolve a staged attachment token (or array of them) into uniform Resolved view(s).
-
.stage_upload(value, backend: nil, uploader: nil) ⇒ Object
SERVER-SIDE staging: turn a submitted attachment value into a token string to stage in
data, minting one from an uploaded file when needed. -
.validation_errors(value, backend: nil, uploader: nil) ⇒ Array<String>
Run the EFFECTIVE Shrine uploader's attacher validations against a staged token (or array of them), returning the validation messages — so a file that violates the uploader's
validate_*rules is rejected at the STEP (stage phase), not deferred toexecute's model assignment.
Class Method Details
.attachment_backend ⇒ Object
The default server-side staging backend: the configured one, else auto-detected (active_shrine loaded → Shrine, else ActiveStorage).
75 76 77 78 |
# File 'lib/plutonium/wizard/attachments.rb', line 75 def Plutonium.configuration.wizards. || (defined?(ActiveShrine) ? :shrine : :active_storage) end |
.field?(input_options) ⇒ Boolean
Whether a step input renders as an attachment (its as: is a file alias),
so its staged token should be resolved for display. Keys off the form's
canonical file-input alias set, so the two never drift.
40 41 42 43 |
# File 'lib/plutonium/wizard/attachments.rb', line 40 def field?() as = &.dig(:options, :as) || &.dig(:as) Plutonium::UI::Form::Base::Builder::FILE_INPUT_TYPES.include?(as&.to_sym) end |
.resolve(value) ⇒ Array<Resolved>
Resolve a staged attachment token (or array of them) into uniform Resolved view(s).
33 34 35 |
# File 'lib/plutonium/wizard/attachments.rb', line 33 def resolve(value) Array(value).filter_map { |token| resolve_token(token) } end |
.stage_upload(value, backend: nil, uploader: nil) ⇒ Object
SERVER-SIDE staging: turn a submitted attachment value into a token string
to stage in data, minting one from an uploaded file when needed.
Handles every shape a step POST can carry for an attachment field:
- an already-minted token String (direct upload, or the hidden preview field on re-submit) → kept verbatim;
- an uploaded file (IO-like) → uploaded to the backend's cache, returning its token (an AS signed_id, or Shrine cached-file JSON);
- blank / no selection → nil (the caller drops the key so the previously staged token survives a Back/re-submit);
- an Array (multiple) → each element mapped, blanks dropped.
63 64 65 66 67 68 69 70 71 |
# File 'lib/plutonium/wizard/attachments.rb', line 63 def stage_upload(value, backend: nil, uploader: nil) if value.is_a?(Array) value.filter_map { |v| stage_upload(v, backend:, uploader:) }.presence elsif value.is_a?(String) value.presence elsif value.respond_to?(:read) upload_to_cache(value, backend || , uploader:) end end |
.validation_errors(value, backend: nil, uploader: nil) ⇒ Array<String>
Run the EFFECTIVE Shrine uploader's attacher validations against a staged
token (or array of them), returning the validation messages — so a file that
violates the uploader's validate_* rules is rejected at the STEP (stage
phase), not deferred to execute's model assignment.
The effective uploader is the field's uploader: if given, else base
Shrine — both of which may carry Attacher.validate rules. Returns []
when the field isn't Shrine-backed (ActiveStorage has no attacher here), when
nothing is staged, or when the effective uploader declares no validations.
94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/plutonium/wizard/attachments.rb', line 94 def validation_errors(value, backend: nil, uploader: nil) return [] unless (backend || ).to_sym == :shrine klass = shrine_uploader(uploader) # Shrine's `validation` plugin is OPTIONAL — without it (or `validation_helpers`) # the Attacher has no `#errors` and nothing to enforce. Detect it up front so a # plugin-less app is a clean no-op, not a per-step rescued NoMethodError. return [] unless klass::Attacher.method_defined?(:errors) Array(value).flat_map { |token| token_validation_errors(klass, token) } end |