I have a Rails 7.1 app and multiple (Rails Engine) Gems with conflicting inflection rules.
There is Gem1::Api::Gem1Controller under app/controllers/gem1/api/gem1_controller.rb
and Gem2::API::Gem2Controller under app/controllers/gem2/api/gem2_controller.rb.
As I understand it, Zeitwerk uses global autoloaders for the whole Rails app including all Rails Engines (which are more or less treated as part of the main app).
By default, Zeitwerk can load Gem1::Api::Gem1Controller, but fails to load Gem2::API::Gem2Controller, because the inflection rule for "api" => "API" is missing.
However, using the "normal" approach of adding custom inflection rules will not work, since then it will fail to load Gem1::Api::Gem1Controller because it expects to find Gem1::API::Gem1Controller.
# config/initializers/zeitwerk.rb
Rails.application.autoloaders.each do |autoloader|
autoloader.inflector.inflect("api" => "API") # works for Gem2, but breaks Gem1 as a result
end
Is there any way to define inflection rules that include the whole namespace? Something like
# config/initializers/zeitwerk.rb
Rails.application.autoloaders.each do |autoloader|
autoloader.inflector.inflect("gem2/api/gem2_controller" => "Gem2::API::Gem2Controller")
end
Or maybe there is a way to define a per-Gem or per-Rails-Engine inflector? Keep in mind it still needs to work as a Rails Engine.
I found a solution for this problem via a custom Inflector. The regular
Rails::Autoloader::Inflector#camelizeignores its second argument, but incorporating the absolute filepath into the camelization enables me to use bothGem1::ApiandGem2::API.