Rails 4:生产环境中不能出现的超类不匹配异常



我目前正在开发一个更大的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

在开发环境中,一切都如预期的那样工作。但是在生产环境中,当应用程序启动并且类正在加载时,当它试图在模块Engine1中加载Global::ConfigurationsController时,我得到Global::BaseControllerSuperclass mismatch异常。

我克服了重命名Engine1::Global::BaseController的问题(暂时),但我不明白为什么这只在生产模式下不起作用?

在重新定义类时发生Superclass mismatch错误。根据你的问题,错误是在BaseController。这是我的理论,看看你的帖子。BaseController被定义了不止一次,所以当这段代码被加载时,BaseController是不明确的:

module Engine1
  class Global::ConfigurationsController < Global::BaseController
  end
end

在加载时,似乎有两个现存的BaseController定义。

# app/controllers/global/base_controller.rb
class Global::BaseController < ApplicationController
end

# app/controllers/global/configurations_controller.rb
class Global::BaseController < Global::BaseController
end

应该加载哪个bascontroller ?对您来说,这里应该做什么是显而易见的,我想我理解您试图在配置中添加间接级别所做的事情。但是Rails在加载时将这两个定义视为相同的名称,并抛出超类错误。


这些是我对你的问题的看法。我很好奇你是怎么想的。

在Rails的生产环境中,控制器的命名空间要严格得多。Rails需要直接的文件夹路径。如果您不希望这样做,那么您应该使用作用域,例如:

scope :path => "account" do
  resources :users
end 

最新更新