From 835b82c8be172054639477f44c9baa15ff3234a7 Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Wed, 30 Sep 2026 11:46:22 -0400 Subject: [PATCH 1/2] Require image_processing 2.2.0 and drop the transform rename image_processing 2.1.0 chose its saver from the destination's extension, so the transform operations encoded to a suffixed sibling of the extensionless scratch path and renamed it into place. Require image_processing 2.2.0, which saves in the `#convert` format to a destination without an extension, and write to the scratch path directly. On the ImageMagick toolchain, a format ImageMagick has no name for, such as `jfif`, now fails as `unreadable` instead of being written in the source's format. ref: https://github.com/janko/image_processing/pull/150 [Fix #4] --- CHANGELOG.md | 6 ++++++ Gemfile.lock | 6 +++--- .../activestorage-hotcell-server.gemspec | 2 +- .../active_storage/hot_cell/server/transforming.rb | 11 ++--------- hotcell-core/lib/hot_cell/descriptors.rb | 5 ++--- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12e92b9..178ca8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,12 @@ Some actions that application developers should consider taking when upgrading f * An application that uses only the Vips transformer no longer needs the `mini_magick` gem. Previously, `require "active_storage/hot_cell/client"` raised `LoadError` when `mini_magick` was not installed. The gem now loads `Transformers::Image::Magick` when the application first names it. +### ActiveStorage::HotCell::Server + +#### Changed + +* The gem requires image_processing 2.2.0. `transformers.image.magick` now fails as `unreadable` for a format ImageMagick has no name for, such as `jfif`, where before it wrote the source's format. (#4) + ### Tooling #### Changed diff --git a/Gemfile.lock b/Gemfile.lock index 9c4c3bf..b49b667 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -72,7 +72,7 @@ PATH specs: activestorage-hotcell-server (0.6.0.dev) hotcell-server (= 0.6.0.dev) - image_processing (>= 2.1.0) + image_processing (>= 2.2.0) mini_magick (>= 5.4.0) ruby-vips (>= 2.2.1) @@ -144,7 +144,7 @@ GEM herb (0.11.0-x86_64-linux-musl) i18n (1.15.2) concurrent-ruby (~> 1.0) - image_processing (2.1.0) + image_processing (2.2.0) io-console (0.9.4) irb (1.18.0) pp (>= 0.6.0) @@ -359,7 +359,7 @@ CHECKSUMS hotcell-core (0.6.0.dev) hotcell-server (0.6.0.dev) i18n (1.15.2) sha256=00f9eb62412fe593b2a65a97daa75300d37abb8f7202ec748e94b6d46a9dd1b5 - image_processing (2.1.0) sha256=ca3814b1b909fc5fab68b261c50eaffef11e29a6907143e9cf1efc14b6dc6f47 + image_processing (2.2.0) sha256=e0cb9892a4395ac2b7bb2fac5c6f5bc63361f2f18ed08773e21fce5b111c6974 io-console (0.9.4) sha256=a403304f32928ee85e56d457b4612ca43f2703b561a3258844992bd24085fbb1 irb (1.18.0) sha256=de9454a0703a54704b9811a5ef31a60c86949fbf4013fcf244fabc7c775248e3 json (3.0.2) sha256=8e6d7e7b11384c21230430cef90b71f14849a34a1f4452796670f7c981bd19df diff --git a/activestorage-hotcell-server/activestorage-hotcell-server.gemspec b/activestorage-hotcell-server/activestorage-hotcell-server.gemspec index 98a87c5..80acafe 100644 --- a/activestorage-hotcell-server/activestorage-hotcell-server.gemspec +++ b/activestorage-hotcell-server/activestorage-hotcell-server.gemspec @@ -27,7 +27,7 @@ Gem::Specification.new do |spec| spec.files = Dir[ "lib/**/*", "MIT-LICENSE", "README.md" ] spec.add_dependency "hotcell-server", version - spec.add_dependency "image_processing", ">= 2.1.0" + spec.add_dependency "image_processing", ">= 2.2.0" spec.add_dependency "mini_magick", ">= 5.4.0" spec.add_dependency "ruby-vips", ">= 2.2.1" end diff --git a/activestorage-hotcell-server/lib/active_storage/hot_cell/server/transforming.rb b/activestorage-hotcell-server/lib/active_storage/hot_cell/server/transforming.rb index ff19395..f218233 100644 --- a/activestorage-hotcell-server/lib/active_storage/hot_cell/server/transforming.rb +++ b/activestorage-hotcell-server/lib/active_storage/hot_cell/server/transforming.rb @@ -14,15 +14,8 @@ def perform(inputs, outputs, format:, operations: {}) format = format.to_s - # ImageProcessing chooses its saver from the destination's extension, and a scratch path has none, - # so encode to a suffixed sibling on the slot's own scratch and adopt it into place. That is one - # rename rather than the copy-out-of-Dir.tmpdir that a destination-less `call` would do, and it - # keeps ImageProcessing's own saver — quality, strip, format defaults — rather than reaching past - # it to the library, which cannot reproduce those without restating them. Output#post makes the - # one remaining copy, out through the caller's descriptor. - encoded = destination.path(extension: format) - pipeline(source, format, operations).call(destination: encoded) - destination.adopt encoded + # A scratch path has no extension, so ImageProcessing saves in the `convert` format. + pipeline(source, format, operations).call(destination: destination.path) describe destination.path, format end diff --git a/hotcell-core/lib/hot_cell/descriptors.rb b/hotcell-core/lib/hot_cell/descriptors.rb index 9dc2190..07008cb 100644 --- a/hotcell-core/lib/hot_cell/descriptors.rb +++ b/hotcell-core/lib/hot_cell/descriptors.rb @@ -140,9 +140,8 @@ class Output < Descriptor # the file back out through the descriptor, and an operation that writes the descriptor directly # never names one at all. # - # `extension` names a suffixed sibling on the same scratch instead, for a producer that picks its - # saver from the extension (ImageProcessing) or appends one of its own (pdftoppm). The sibling is - # not what post ships: adopt renames it into place. + # `extension` names a suffixed sibling on the same scratch instead, for a producer that appends an + # extension of its own (pdftoppm). The sibling is not what post ships: adopt renames it into place. def path(extension: nil) base = (@path ||= scratch_path) extension.nil? ? base : "#{base}.#{extension}" From e83284f5842134dd312e4db0a44d0cbd9de22aa4 Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Wed, 30 Sep 2026 15:26:29 -0400 Subject: [PATCH 2/2] Describe the image_processing 2.2.0 upgrade as an improvement The CHANGELOG entry described a known edge case that a separate fix will handle, and did not mention the rename every transform now saves. --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 178ca8e..3b96e8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,9 +58,9 @@ Some actions that application developers should consider taking when upgrading f ### ActiveStorage::HotCell::Server -#### Changed +#### Improved -* The gem requires image_processing 2.2.0. `transformers.image.magick` now fails as `unreadable` for a format ImageMagick has no name for, such as `jfif`, where before it wrote the source's format. (#4) +* The transform operations write their output straight to its final path, saving a file rename on every transform. This needs image_processing 2.2.0, which the gemspec now requires. (#4) ### Tooling