I am currently working on a bigger rails application, that uses engines for sub applications, with the following folder structure:
- app
\- controllers
\- global
\- base_controller.rb
\- configurations_controller.rb
\- application_controller.rb
- ...
- engines
\- engine_1
\- app
\- controllers
\- engine_1
\- application_controller.rb
\- global
\- base_controller.rb
\- configurations_controller.rb
- ...
The setup of the controllers is as follows:
# app/controllers/global/base_controller.rb
class Global::BaseController < ApplicationController
end
# app/controllers/global/configurations_controller.rb
class Global::BaseController < Global::BaseController
end
# engines/engine_1/app/controllers/engine_1/application_controller.rb
module Engine1
class ApplicationController < ::ApplicationController
end
end
# engines/engine_1/app/controllers/engine_1/global/base_controller.rb
require_dependency "engine_1/application_controller"
module Engine1
class Global::BaseController < ApplicationController
end
end
# engines/engine_1/app/controllers/engine_1/global/configurations_controller.rb
module Engine1
class Global::ConfigurationsController < Global::BaseController
end
end
My routes files
# config/routes.rb
Rails.application.routes.draw do
namespace :global do
resource :configuration, only: [:show, :update]
end
mount Engine1::Engine, at: '/engine_1', as: :engine_1
end
# engines/engine_1/config/routes.rb
Engine1::Engine.routes.draw do
namespace :global do
resource :configuration, only: [:show, :update]
end
end
In development environment everything works as expected. But in production environment, when the application gets started and classes are being eager loaded, I get a Superclass mismatch
exception for Global::BaseController
when it tries to load the Global::ConfigurationsController
in module Engine1
.
I overcame the problem (temporarily) in renaming the Engine1::Global::BaseController
but I don't understand why this is not working in production mode only?
The Superclass mismatch
error happens when there is a re-definition of a class. According to your question, the error is on BaseController. Here's my theory looking at what you've posted. BaseController is being defined more than once, so that when this code is loaded the BaseController is ambiguous:
module Engine1
class Global::ConfigurationsController < Global::BaseController
end
end
It appears that at load time there are 2 definitions extant of BaseController.
# app/controllers/global/base_controller.rb
class Global::BaseController < ApplicationController
end
# app/controllers/global/configurations_controller.rb
class Global::BaseController < Global::BaseController
end
So which BaseController should be loaded? To you it is obvious what should be done here, and I think I understand what you're trying to do with adding a level of indirection to your configuration. But Rails sees these two definitions as the same name at load time and throws the superclass error.
These are my thoughts about your question. I'm curious what you think.