Rails4: 生产环境超类不匹配异常不能
Rails 4: Superclass mismatch exception in production environment that can't be
我目前正在开发一个更大的 rails 应用程序,它使用子应用程序的引擎,具有以下文件夹结构:
- 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
- ...
控制器设置如下:
# 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
我的路线文件
# 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
在开发环境中一切正常。但是在生产环境中,当应用程序启动并且正在急切加载 类 时,当它尝试加载模块 Global::ConfigurationsController
时,Global::BaseController
出现 Superclass mismatch
异常=17=].
我克服了重命名 Engine1::Global::BaseController
的问题(暂时),但我不明白为什么这不能仅在生产模式下工作?
当您在 Rails 中进行生产时,控制器的命名空间要严格得多。 Rails 需要直接文件夹路径。如果您不想这样做,那么您应该使用范围界定,例如:
scope :path => "account" do
resources :users
end
Superclass mismatch
错误发生在重新定义 class 时。根据你的问题,错误是在 BaseController 上。这是我根据您发布的内容得出的理论。 BaseController 被定义了不止一次,所以当加载这段代码时,BaseController 是不明确的:
module Engine1
class Global::ConfigurationsController < Global::BaseController
end
end
似乎在加载时有 2 个现存的 BaseController 定义。
# app/controllers/global/base_controller.rb
class Global::BaseController < ApplicationController
end
# app/controllers/global/configurations_controller.rb
class Global::BaseController < Global::BaseController
end
那么应该加载哪个BaseController?对您来说,这里应该做什么是显而易见的,而且我想我理解您在为配置添加间接级别时想要做什么。但是 Rails 在加载时将这两个定义视为同名并抛出 superclass 错误。
这些是我对你的问题的看法。我很好奇你的想法。
我目前正在开发一个更大的 rails 应用程序,它使用子应用程序的引擎,具有以下文件夹结构:
- 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
- ...
控制器设置如下:
# 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
我的路线文件
# 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
在开发环境中一切正常。但是在生产环境中,当应用程序启动并且正在急切加载 类 时,当它尝试加载模块 Global::ConfigurationsController
时,Global::BaseController
出现 Superclass mismatch
异常=17=].
我克服了重命名 Engine1::Global::BaseController
的问题(暂时),但我不明白为什么这不能仅在生产模式下工作?
当您在 Rails 中进行生产时,控制器的命名空间要严格得多。 Rails 需要直接文件夹路径。如果您不想这样做,那么您应该使用范围界定,例如:
scope :path => "account" do
resources :users
end
Superclass mismatch
错误发生在重新定义 class 时。根据你的问题,错误是在 BaseController 上。这是我根据您发布的内容得出的理论。 BaseController 被定义了不止一次,所以当加载这段代码时,BaseController 是不明确的:
module Engine1
class Global::ConfigurationsController < Global::BaseController
end
end
似乎在加载时有 2 个现存的 BaseController 定义。
# app/controllers/global/base_controller.rb
class Global::BaseController < ApplicationController
end
# app/controllers/global/configurations_controller.rb
class Global::BaseController < Global::BaseController
end
那么应该加载哪个BaseController?对您来说,这里应该做什么是显而易见的,而且我想我理解您在为配置添加间接级别时想要做什么。但是 Rails 在加载时将这两个定义视为同名并抛出 superclass 错误。
这些是我对你的问题的看法。我很好奇你的想法。