mobility_active_storage 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f4973582dfa47dc2c6bdd8f1003bf6b3e4347be60ab61ab653e588629cee3588
4
- data.tar.gz: fbc607bf032ac1c19dc3f73ce41ceabba5ce8372e2cb71977158a8f17bc45e55
3
+ metadata.gz: 7ed33baa135ecd69527c111652956b1420c0bce45052b3725cc5d4e55715257e
4
+ data.tar.gz: ff07c4fd501a56b1b57008d7f294517c5159d27ef4c7844984012251b9b49343
5
5
  SHA512:
6
- metadata.gz: 7cc3a587ed7f117a685b9d7236597a3b50eef206537e83554e27b32ac9d803560d08f93f99e2df554afee1af1cf558d6025942da2b9bd8c4514d36d63e6cde49
7
- data.tar.gz: fbb2f83b8e98ea1f26019a2302fab216dd7fd9b6b677a09e5fb1b785766ed149e6df0c5479e27cac85f92748474f49637791e47953c51fae215ba1bc61e69abe
6
+ metadata.gz: 776fef9bd8b7dffb06b3e1b4c9955bb3b5acebec0e601d265df4793dfcb98e5e7f5a12d9aeec8992cfed204b832201cbc38a7bdd5f8894edb8bcd0db418508f7
7
+ data.tar.gz: b62a6b3ae3dad73be4f415f1753fd3af573efb2c0e72b87fd57b09820a8a651f80e041587b95a91c7be3c0756dd3dfe9d605f282a106df4a10702d7cd2813254
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.2] - 2026-08-11
4
+
5
+ - `#{attribute}_locales` now answers in one query instead of one per configured locale. It probed
6
+ each locale's attachment proxy in turn, so a model declared for 73 locales issued 73 statements
7
+ every time it was asked -- and any caller that reads it per row (a serializer, a validation) paid
8
+ that per row. Pending attachment changes still take precedence over the stored rows, so a staged
9
+ attach counts before it is saved and a staged purge stops counting straight away.
10
+
3
11
  ## [0.1.1] - 2026-08-10
4
12
 
5
13
  - No user-facing changes. Released to verify the trusted-publishing workflow; the packaged files
data/README.md CHANGED
@@ -94,6 +94,10 @@ For `has_one_translated_attached :document`:
94
94
 
95
95
  `has_many_translated_attached :photos` mirrors these with `ActiveStorage::Attached::Many`.
96
96
 
97
+ `document_locales` costs one query however many locales the attribute declares, and counts pending
98
+ changes the way `attached?` does: a staged attach is included before it is saved, a staged purge
99
+ excluded straight away. It does not memoize, so hold the result if you need it more than once.
100
+
97
101
  ### Fallbacks
98
102
 
99
103
  Off by default. Enable per attribute:
@@ -50,6 +50,13 @@ module MobilityActiveStorage
50
50
  normalized_locales.include?(Mobility.normalize_locale(locale))
51
51
  end
52
52
 
53
+ # Every configured locale's attachment name. Memoized per attribute: the locale set is
54
+ # fixed when the class body runs.
55
+ def attachment_names(attribute)
56
+ @attachment_names ||= {}
57
+ @attachment_names[attribute] ||= normalized_locales.map { |locale| "#{attribute}_#{locale}" }
58
+ end
59
+
53
60
  # Mobility's query plugin asks the backend for an Arel node so it can build a predicate.
54
61
  # An attachment is a row in active_storage_attachments, not a comparable column value, so
55
62
  # there is nothing meaningful to compare. Fail with an explanation rather than the
@@ -136,8 +143,24 @@ module MobilityActiveStorage
136
143
  end
137
144
 
138
145
  # Yields each configured locale that actually has an attachment.
146
+ #
147
+ # One query for the whole locale set, not one per locale: every locale is a row in
148
+ # active_storage_attachments under a suffixed name, so which locales are present is a single
149
+ # pluck on that table. Probing each proxy instead costs a query per configured locale, and a
150
+ # model declared for a large locale set pays that on every read -- 73 statements to answer a
151
+ # question one statement answers.
152
+ #
153
+ # Pending changes win over the stored rows, as Active Storage's own +attached?+ does: an
154
+ # attach counts before it is saved, a purge stops counting straight away.
139
155
  def each_locale
140
- options[:locales].each { |locale| yield locale if attached(locale).attached? }
156
+ persisted = persisted_attachment_names
157
+
158
+ options[:locales].each do |locale|
159
+ name = attachment_name(locale)
160
+ # attached? reads the staged change without touching the database.
161
+ present = model.attachment_changes.key?(name) ? attached(locale).attached? : persisted.include?(name)
162
+ yield locale if present
163
+ end
141
164
  end
142
165
 
143
166
  # The Active Storage proxy for +locale+, without any fallback handling.
@@ -149,6 +172,20 @@ module MobilityActiveStorage
149
172
 
150
173
  private
151
174
 
175
+ # Which of this attribute's attachment names have rows. distinct because a collection
176
+ # attachment repeats its name once per file, and polymorphic_name so an STI subclass looks
177
+ # itself up under the type Active Storage actually stored.
178
+ def persisted_attachment_names
179
+ return Set.new if model.new_record?
180
+
181
+ ActiveStorage::Attachment
182
+ .where(record_type: model.class.polymorphic_name, record_id: model.id,
183
+ name: self.class.attachment_names(attribute))
184
+ .distinct
185
+ .pluck(:name)
186
+ .to_set
187
+ end
188
+
152
189
  def attachment_name(locale)
153
190
  self.class.attachment_name_for(attribute, locale)
154
191
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MobilityActiveStorage
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mobility_active_storage
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Glen Barnes