当加载根命名空间中的另一个同名类时,Rails类加载会跳过命名空间类

我有两个名称空间,每个名称空间都有自己的控制器和演示者类: Member::DocumentsController Member::DocumentPresenter Guest::DocumentsController Guest::DocumentPresenter

两位演示者都inheritance自::DocumentPresenter

控制器在没有指定名称空间的情况下访问各自的演示者,例如:

 class Guest::DocumentsController < ActionController::Base def show DocumentPresenter.new(find_document) end end 

这通常会在同一名称空间内调用presenter。 但有时在开发环境中我看到base :: DocumentPresenter正在使用中。

我怀疑原因是base :: DocumentPresenter已经加载了,所以Rails类自动加载并不需要进一步查看。 这可能是这种情况吗? 它也可以在生产环境中发生吗?

我可以想到两个解决方案:

  • 将基类重命名为DocumentPresenterBase
  • 在控制器文件中明确要求适当的presenter文件

有更好的解决方案吗?

你的假设是正确的 – 如果你没有指定命名空间,Ruby从当前命名空间开始并一直向上找到类,并且因为命名空间类还没有自动加载,所以找到::DocumentPresenter并且自动加载器不会触发。

作为一种解决方案,我建议将::DocumentPresenter重命名为DocumentPresenterBase ,因为当您忘记命名空间或明确要求某处时,这可以保护您免受错误的影响。

要考虑的第二个选项实际上是在整个地方使用特定的命名空间类名,但是当你不小心忘记命名空间某些调用时,这会遇到错误。

 class Guest::DocumentsController < ActionController::Base def show Guest::DocumentPresenter.new(find_document) end end 

第三个选项将是您的第二个选项 - 事先明确要求初始化程序中的所有类。 我用Rails API完成了这个操作,它接收JSON嵌入式模型,并且当实际模型尚未加载时,Rails倾向于命名它们。

选项3.5您可能会欺骗自动加载器来完成繁重的工作(但是,这可能看起来更像是一个黑客):

 class Guest::DocumentsController < ActionController::Base # trigger autoload Guest::DocumentPresenter def show # This should refer Guest::DocumentPresenter DocumentPresenter.new(find_document) end def show # As will this DocumentPresenter.new(find_document) end end 

仍然最干净的是重命名基类。

我想在3个解决方案中如果你想要mantein这个名字,那么你的第二个解决方案就是。

1)在控制器文件中明确要求适当的presenter文件

2)执行完整的环境类路径,如:

 class Guest::DocumentsController < ActionController::Base def show Guest::DocumentPresenter.new(find_document) end end 

3)在initialize目录上创建一个文件并手动执行require(最差的选项:S)

Interesting Posts