Allow config.active_storage.variant_processor to be set to a class
From uloza+hey@proton.me · original ↗ · unsubscribe
The class must implement the interface defined by ActiveStorage::Transformers::Transformer. Active Storage then uses it for variant processing
Allow `config.active_storage.variant_processor` to be set to a class by flavorjones · Pull Request #58384 · rails/rails · GitHub
Navigation Menu
Appearance settings
-
Platform
-
AI CODE CREATION
-
DEVELOPER WORKFLOWS
-
APPLICATION SECURITY
-
EXPLORE
-
-
Solutions
-
BY COMPANY SIZE
-
BY USE CASE
-
BY INDUSTRY
-
-
Resources
-
EXPLORE BY TOPIC
-
EXPLORE BY TYPE
-
SUPPORT & SERVICES
-
-
Open Source
-
COMMUNITY
-
PROGRAMS
-
REPOSITORIES
-
-
Enterprise
Search/
Appearance settings
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session. Dismiss alert
Uh oh!
There was an error while loading. Please reload this page.
- Notifications You must be signed in to change notification settings
- Fork 22.4k
- Code
- Issues 485
- Pull requests 1.1k
- Discussions
- Actions
- Security and quality 26
- Insights
Additional navigation options
Allow config.active_storage.variant_processor to be set to a class - #58384
#58384
Merged
flavorjones merged 1 commit into
rails:mainrails/rails:mainfrom
flavorjones:variant-transformer-seamflavorjones/rails:variant-transformer-seamCopy head branch name to clipboard
Aug 7, 2026
ConversationCommits1 (1)ChecksFiles changed
Merged
##
Allow config.active_storage.variant_processor to be set to a class#58384
flavorjones merged 1 commit into
rails:mainrails/rails:mainfrom
flavorjones:variant-transformer-seamflavorjones/rails:variant-transformer-seamCopy head branch name to clipboard
Conversation
###
flavorjones commented Aug 5, 2026
Copy link
Copy Markdown
Member
Motivation / Background
Active Storage passes attachment bytes to a media library in three operations: analysis, preview generation, and variant processing. An application can replace the code for two of them: config.active_storage.analyzers and config.active_storage.previewers each accept an array of classes.
Variant processing has no equivalent. config.active_storage.variant_processor accepts only :vips, :mini_magick, and :disabled (though, note that ActiveStorage::Engine maps those symbols to a class):
ActiveStorage.variant_transformer = case ActiveStorage.variant_processor when :disabled ActiveStorage::Transformers::NullTransformer when :vips ActiveStorage::Transformers::Vips when :mini_magick ActiveStorage::Transformers::ImageMagick end
ActiveStorage.variant_transformer is an undocumented mattr_accessor, so an application cannot use it directly.
This gap makes it challenging to experiment with variant processors, for example to play around with sandboxing image transformations.
Detail
config.active_storage.variant_processor now accepts a class, in addition to :vips, :mini_magick, and :disabled. The class must implement the interface defined by ActiveStorage::Transformers::Transformer in order to behave properly, though that is not explicitly checked. Active Storage then uses it for variant processing.
config.active_storage.variant_processor = CustomTransformer
Note that the built-in image analyzers accept a blob only when variant_processor is :vips or :mini_magick, so setting this configuration to a custom class requires adding a custom analyzer to config.active_storage.analyzers as well (for now).
One notable change: an unrecognized value now raises ArgumentError while booting, instead of failing later with NoMethodError when a variant is generated. I think this is a good thing.
Additional information
This change only adds the abstraction layer. It does not add any custom or additional transformers.
Active Storage does not check the type of the configured class. The class does not have to subclass ActiveStorage::Transformers::Transformer. It only has to implement the same interface.
The allowlist for transformation names and arguments is in ActiveStorage::Transformers::ImageMagick, and ActiveStorage::Transformers::Vips does not apply it. I think that it’s worth moving that validation to the analyzer/transformer/previewer classes, but should be done in a separate PR.
Checklist
Before submitting the PR make sure the following are checked:
- This Pull Request is related to one change. Unrelated changes should be opened in separate PRs.
- Commit message has a detailed description of what changed and why. If this PR fixes a related issue include it in the commit message. Ex:
[Fix #issue-number] - Tests are added or updated if you fix a bug or add a feature.
- CHANGELOG files are updated for the changed libraries if there is a behavior change or additional feature. Minor bug fixes and documentation changes should not be included.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
All reactions github-actions Bot added railties docs activestorage labels Aug 5, 2026
flavorjones requested a lite review from Copilot August 6, 2026 02:34
Copilot started reviewing on behalf of flavorjones August 6, 2026 02:35 View session
Copilot AI reviewed Aug 6, 2026
###
Copilot AI left a comment
Copy link
Copy Markdown
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality Hide comment
Pull request overview
This PR extends Active Storage’s configuration to allow config.active_storage.variant_processor to be set to a transformer class (in addition to the existing :vips, :mini_magick, and :disabled symbols), enabling applications to plug in custom variant processing implementations.
Changes:
- Update Active Storage engine initialization to accept a class-based
variant_processorand raiseArgumentErrorfor unknown values during boot. - Add integration tests covering both the class-based configuration path and the new boot-time error behavior.
- Document the new configuration option in the Guides, API docs, and the Active Storage changelog.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
File
Description
activestorage/lib/active_storage/engine.rb
Accept transformer classes for variant_processor and raise early for unknown values.
railties/test/application/active_storage/engine_integration_test.rb
Adds coverage for class-based configuration and unknown-value error behavior.
railties/test/application/active_storage/custom_processors_integration_test.rb
New integration test demonstrating a custom analyzer + custom transformer end-to-end.
guides/source/configuring.md
Documents class-based variant_processor and notes analyzer implications.
activestorage/lib/active_storage/transformers/transformer.rb
Clarifies the custom transformer interface contract in documentation.
activestorage/app/models/active_storage/variant.rb
Updates public docs to reflect that only built-in transformers require image_processing.
activestorage/CHANGELOG.md
Adds changelog entry describing the new configuration behavior.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
All reactions
Comment thread railties/test/application/active_storage/custom_processors_integration_test.rb Show resolved Hide resolved
Uh oh!
There was an error while loading. Please reload this page.
flavorjones force-pushed the variant-transformer-seam branch from bb9fca0 to 05cb696 Compare August 6, 2026 02:44
[Allow `config.active_storage.variant_processor` to be set to a class](/rails/rails/pull/58384/commits/54cbc21ce0ec848f77b3d3513e8e53de5eff864f "Allow `config.active_storage.variant_processor` to be set to a class Active Storage passes attachment bytes to a media library in three operations: analysis, preview generation, and variant processing. An application could replace the code for two of them, through `config.active_storage.analyzers` and `config.active_storage.previewers`. Variant processing had no equivalent. `config.active_storage.variant_processor` accepted only `:vips`, `:mini_magick`, and `:disabled`, and the engine assigned `ActiveStorage.variant_transformer` in `config.after_initialize`, so an application that set it in an initializer lost the value. That made it challenging to opt into experimental variant processing, for example to play around with sandboxing image transformations. `config.active_storage.variant_processor` will also accept a class, in addition to `:vips`, `:mini_magick`, and `:disabled`. The class must implement the interface defined by `ActiveStorage::Transformers::Transformer`. Active Storage will then use it for variant processing. Note that the built-in image analyzers accept a blob only when `variant_processor` is `:vips` or `:mini_magick`, so setting this configuration to a custom class will require adding a custom analyzer to `config.active_storage.analyzers` as well. An unrecognized value will raise `ArgumentError` while booting, instead of failing later with `NoMethodError` when a variant is generated.") …
[54cbc21](/rails/rails/pull/58384/commits/54cbc21ce0ec848f77b3d3513e8e53de5eff864f)
Active Storage passes attachment bytes to a media library in three operations: analysis, preview generation, and variant processing. An application could replace the code for two of them, through `config.active_storage.analyzers` and `config.active_storage.previewers`. Variant processing had no equivalent. `config.active_storage.variant_processor` accepted only `:vips`, `:mini_magick`, and `:disabled`, and the engine assigned `ActiveStorage.variant_transformer` in `config.after_initialize`, so an application that set it in an initializer lost the value. That made it challenging to opt into experimental variant processing, for example to play around with sandboxing image transformations.
`config.active_storage.variant_processor` will also accept a class, in addition to `:vips`, `:mini_magick`, and `:disabled`. The class must implement the interface defined by `ActiveStorage::Transformers::Transformer`. Active Storage will then use it for variant processing. Note that the built-in image analyzers accept a blob only when `variant_processor` is `:vips` or `:mini_magick`, so setting this configuration to a custom class will require adding a custom analyzer to `config.active_storage.analyzers` as well. An unrecognized value will raise `ArgumentError` while booting, instead of failing later with `NoMethodError` when a variant is generated.
flavorjones force-pushed the variant-transformer-seam branch from 05cb696 to 54cbc21 Compare August 6, 2026 02:44
flavorjones requested a review from jeremy August 7, 2026 19:17
jeremy added this to the 8.2.0 milestone Aug 7, 2026
jeremy approved these changes Aug 7, 2026
###
flavorjones commented Aug 7, 2026
Copy link
Copy Markdown
Member Author
Note for posterity: I had a side chat with @jeremy about using straight class references here (and in the other existing config params config.active_storage.analyzers and config.active_storage.previewers) where he pointed out the “lumpy” conventions currently in use.
Specifically:
- config.active_storage.variant_processor currently takes a snake case symbol, which might reasonably be expected to extend like config.session_store where the symbol is classified and resolved under a fixed namespace
- but the analyzers and previewers are configured with a straight array of
Classreferences - and that the use of
Classreferences can defeat much of the boot-time ordering in Rails, resulting in early loads or failures to reload in development
So if this is merged I’ll plan to follow up with another PR that would add support for the following configuration conventions:
- snake case symbol (classified and resolved under a documented namespace)
- class name (resolved when needed, and at reload)
- literal class references
across all three active storage processor config params.
All reactions
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Hide details View details
flavorjones merged commit 5ea765e into rails:main Aug 7, 2026
5 checks passed
Uh oh!
There was an error while loading. Please reload this page.
julianrubisch mentioned this pull request Aug 8, 2026
Activestorage transformers for custom media types #58398
Open
4 tasks
flavorjones mentioned this pull request Aug 14, 2026
(saas-only) Process Active Storage attachments in a HotCell cell basecamp/fizzy#3034
Open
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
### Reviewers
Copilot review effort Lite
- Lite Efficient review, low cost
- Balanced Deep analysis, moderate cost
- Max Most thorough, high cost Coming soon
Applies to this pull request for everyone.Learn more about Copilot code review.
jeremy jeremy approved these changes
Assignees
No one assigned
Labels
Projects
None yet
Milestone
Development
Successfully merging this pull request may close these issues.
Uh oh!
There was an error while loading. Please reload this page.
3 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Footer
Footer navigation
- Terms
- Privacy
- Security
- Status
- Community
- Docs
- Contact
- Manage cookies
- Do not share my personal information
You can’t perform that action at this time.