From 0d53ad690104a16ec9f2ee18be62a7aa2e52f9e0 Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Mon, 28 Sep 2026 17:27:24 -0400 Subject: [PATCH] Stop requiring mini_magick for apps on the Vips transformer Requiring activestorage-hotcell-client loaded the ImageMagick transformer, whose Rails superclass requires mini_magick. Under image_processing 2.x, which no longer depends on mini_magick, an application on the Vips transformer failed to boot with LoadError. Autoload the ImageMagick transformer, so only an application that names it needs mini_magick. [Fix #57] --- CHANGELOG.md | 6 ++++ .../lib/active_storage/hot_cell/client.rb | 5 ++- .../test/transformers/image_magick_test.rb | 34 +++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e1a866..12e92b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,12 @@ Some actions that application developers should consider taking when upgrading f * New gem `yabeda-hotcell`. It publishes Yabeda metrics for the application side. Call `Yabeda::HotCell.install!` one time at boot. The gem counts each call by cell, operation, code and cause, and measures the time the cell spent. On each scrape, it reads the counters of each registered cell. See the README's "Metrics collection". +### ActiveStorage::HotCell::Client + +#### Fixed + +* 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. + ### Tooling #### Changed diff --git a/activestorage-hotcell-client/lib/active_storage/hot_cell/client.rb b/activestorage-hotcell-client/lib/active_storage/hot_cell/client.rb index 0af50a1..0fd84b6 100644 --- a/activestorage-hotcell-client/lib/active_storage/hot_cell/client.rb +++ b/activestorage-hotcell-client/lib/active_storage/hot_cell/client.rb @@ -6,7 +6,10 @@ require "active_storage/hot_cell/client/version" require "active_storage/hot_cell/client/operations" require "active_storage/hot_cell/client/transformers/image/vips" -require "active_storage/hot_cell/client/transformers/image/magick" +# Autoloaded because it subclasses Rails' ImageMagick transformer, which requires mini_magick, and an application +# on vips need not bundle that gem. +ActiveStorage::HotCell::Client::Transformers::Image.autoload :Magick, + "active_storage/hot_cell/client/transformers/image/magick" require "active_storage/hot_cell/client/analyzers/image/vips" require "active_storage/hot_cell/client/analyzers/image/magick" require "active_storage/hot_cell/client/analyzers/video/ffprobe" diff --git a/activestorage-hotcell-client/test/transformers/image_magick_test.rb b/activestorage-hotcell-client/test/transformers/image_magick_test.rb index 39ce3ec..c5792d4 100644 --- a/activestorage-hotcell-client/test/transformers/image_magick_test.rb +++ b/activestorage-hotcell-client/test/transformers/image_magick_test.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require "test_helper" +require "open3" class TransformersImageMagickTest < ActiveStorageHotCellClientTest def test_it_yields_an_open_rewound_tempfile_of_the_converted_image @@ -52,7 +53,40 @@ def test_a_cell_that_is_not_there_raises_the_transient_class end end + # image_processing 2.x no longer depends on mini_magick, so an application on vips may not have it. Only a + # fresh process can show what requiring the gem loads, and a stand-in first on the load path makes + # `require "mini_magick"` fail the way it does when the gem is not installed. Rails is loaded first, as + # Bundler.require does in an application, so the railtie is loaded too. + def test_the_gem_loads_without_mini_magick + output, status = ruby_without_mini_magick <<~RUBY + require "rails" + require "activestorage-hotcell-client" + RUBY + + assert_predicate status, :success?, output + end + + def test_naming_the_transformer_without_mini_magick_raises_load_error + output, status = ruby_without_mini_magick <<~RUBY + require "active_storage/hot_cell/client" + puts "loaded" + ActiveStorage::HotCell::Client::Transformers::Image::Magick + RUBY + + refute_predicate status, :success? + assert_match(/^loaded$/, output) + assert_match "requires the mini_magick gem", output + end + private + def ruby_without_mini_magick(script) + Dir.mktmpdir "hotcell-no-mini-magick" do |dir| + File.write File.join(dir, "mini_magick.rb"), 'raise LoadError, "cannot load such file -- mini_magick"' + + Open3.capture2e RbConfig.ruby, "-I", dir, "-I", File.expand_path("../../lib", __dir__), "-e", script + end + end + def transformer(transformations) ActiveStorage::HotCell::Client::Transformers::Image::Magick.new transformations end