我有两个名称空间,每个名称空间都有自己的控制器和演示者类:
Member::DocumentsController
Member::DocumentPresenter
Guest::DocumentsController
Guest::DocumentPresenter
两位演示者都继承自::DocumentPresenter
。
控制器访问各自没有指定名称空间的演示者,例如:
class Guest::DocumentsController < ActionController::Base
def show
DocumentPresenter.new(find_document)
end
end
这通常会在同一名称空间内调用presenter。但是有时在开发环境中我看到正在使用base :: DocumentPresenter。
我怀疑原因是base :: DocumentPresenter已经加载了,所以Rails类自动加载并不需要进一步查看。这可能是这种情况吗?它也可以在生产环境中发生吗?
我可以想到两个解决方案:
有更好的解决方案吗?
答案 0 :(得分:3)
你的假设是正确的 - 如果你没有指定命名空间,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
最干净的是重命名基类。
答案 1 :(得分:1)
我认为在3个解决方案中,如果你想要mantein这个名字,那么你的第二个解决方案。
1)在控制器文件中明确要求适当的presenter文件
2)执行完整的环境类路径,如:
class Guest::DocumentsController < ActionController::Base
def show
Guest::DocumentPresenter.new(find_document)
end
end
3)在initialize目录上创建一个文件并手动执行require(最差的选项:S)