Module: MobilityActiveStorage::BackendMethods
- Included in:
- Backend, ManyBackend
- Defined in:
- lib/mobility_active_storage/backend_methods.rb,
sig/mobility_active_storage.rbs
Overview
Behaviour shared by the has_one and has_many attachment backends.
A translated attachment is stored as N ordinary Active Storage attachments whose
name column carries the locale, e.g. document_en and document_fr. Each one is
declared with a real has_one_attached / has_many_attached in the backend's setup
block, so Rails' own associations, upload callbacks, scopes and purge-on-destroy
behaviour apply unchanged.
Backends must include Mobility::Backend before this module, so that the overrides here
(notably each_locale and present?) take precedence over Mobility::Backend's generic
implementations.
Defined Under Namespace
Modules: ClassMethods Classes: FallbackChain
Class Method Summary collapse
Instance Method Summary collapse
-
#attached(locale) ⇒ Object
The Active Storage proxy for
locale, without any fallback handling. -
#each_locale {|arg0| ... } ⇒ void
Yields each configured locale that actually has an attachment.
-
#present?(locale, **options) ⇒ Boolean
Whether the attribute has an attachment in
locale(honouring fallbacks). -
#read(locale, fallback: true, **kwargs) ⇒ ActiveStorage::Attached::One, ActiveStorage::Attached::Many
Returns the Active Storage proxy for
locale. -
#write(locale, value) ⇒ Object
Stages the attachment change for
locale.
Class Method Details
.included(base) ⇒ Object
18 19 20 21 22 |
# File 'lib/mobility_active_storage/backend_methods.rb', line 18 def self.included(base) raise Error, "#{base} must include Mobility::Backend before #{self}" unless base < Mobility::Backend base.extend(ClassMethods) end |
Instance Method Details
#attached(locale) ⇒ Object
The Active Storage proxy for locale, without any fallback handling.
167 168 169 170 171 |
# File 'lib/mobility_active_storage/backend_methods.rb', line 167 def attached(locale) @attached ||= {} @attached[Mobility.normalize_locale(locale)] ||= attached_class.new((locale), model) end |
#each_locale {|arg0| ... } ⇒ void
This method returns an undefined value.
Yields each configured locale that actually has an attachment.
One query for the whole locale set, not one per locale: every locale is a row in active_storage_attachments under a suffixed name, so which locales are present is a single pluck on that table. Probing each proxy instead costs a query per configured locale, and a model declared for a large locale set pays that on every read -- 73 statements to answer a question one statement answers.
Pending changes win over the stored rows, as Active Storage's own attached? does: an
attach counts before it is saved, a purge stops counting straight away.
155 156 157 158 159 160 161 162 163 164 |
# File 'lib/mobility_active_storage/backend_methods.rb', line 155 def each_locale persisted = [:locales].each do |locale| name = (locale) # attached? reads the staged change without touching the database. present = model..key?(name) ? attached(locale).attached? : persisted.include?(name) yield locale if present end end |
#present?(locale, **options) ⇒ Boolean
Whether the attribute has an attachment in locale (honouring fallbacks).
141 142 143 |
# File 'lib/mobility_active_storage/backend_methods.rb', line 141 def present?(locale, **) read(locale, **).attached? end |
#read(locale, fallback: true, **kwargs) ⇒ ActiveStorage::Attached::One, ActiveStorage::Attached::Many
Returns the Active Storage proxy for locale.
Always returns a proxy, never nil, so that record.document.attach(...) works on a
record with nothing attached yet. Falls back to another locale only when the attribute
was configured with fallbacks and the current locale has nothing attached.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/mobility_active_storage/backend_methods.rb', line 111 def read(locale, fallback: true, **kwargs) proxy = attached(locale) return proxy if proxy.attached? # Mobility's convention: an explicitly requested locale never falls back. return proxy if fallback == false || kwargs[:locale] fallback_locale = fallback_chain(locale, fallback).find do |candidate| configured?(candidate) && attached(candidate).attached? end return proxy unless fallback_locale # Reads resolve through the fallback locale; writes stay in the requested locale. fallback_attached_class.new((locale), model, (fallback_locale)) end |
#write(locale, value) ⇒ Object
Stages the attachment change for locale.
Deliberately mutates attachment_changes rather than calling attach.
ActiveStorage::Attached::One#attach is implemented as
record.public_send("document_en=", attachable), and Mobility's locale accessors take
precedence over Active Storage's generated writer -- so calling attach here would
re-enter this same method. Writing the change directly makes both entry paths converge.
134 135 136 137 138 |
# File 'lib/mobility_active_storage/backend_methods.rb', line 134 def write(locale, value, **) name = (locale) model.[name] = build_change(name, value) value end |