问题描述
我有两个命名空间,每个命名空间都有自己的控制器和演示者类:
Member :: DocumentsController
Member: :DocumentPresenter
来宾:: DocumentsController
来宾:: DocumentPresenter
I have two namespaces, each with its own controller and presenter classes:Member::DocumentsController
Member::DocumentPresenter
Guest::DocumentsController
Guest::DocumentPresenter
两个演示者都从 :: DocumentPresenter
继承。
控制器在未指定名称空间的情况下访问其各自的演示者,例如:
Controllers access their respective presenters without namespace specified, e.g.:
class Guest::DocumentsController < ActionController::Base
def show
DocumentPresenter.new(find_document)
end
end
这通常在相同名称空间中调用主持人。但是有时在开发环境中,我看到正在使用基本:: DocumentPresenter。
This usually calls presenter within same namespace. However sometimes in development environment I see base ::DocumentPresenter is being used.
我怀疑原因是基本:: DocumentPresenter已经加载,因此Rails类会自动加载不用再去寻找了。可能是这样吗?它也可以在生产环境中发生吗?
I suspect the cause is that base ::DocumentPresenter is already loaded, so Rails class auto-loading doesn't bother to look further. Is this likely the case? Can it happen in production environment too?
我可以想到两种解决方案:
I can think of two solutions:
- 将基类重命名为DocumentPresenterBase
- 在控制器文件中明确要求适当的演示者文件
是有更好的解决方案吗?
Is there a better solution?
推荐答案
您的假设是正确的-如果未指定名称空间,则Ruby从当前名称空间开始,努力找到该类,并且由于尚未自动加载命名空间的类,因此找到了 :: DocumentPresenter
,并且自动加载器未触发。
You are correct in your assumptions - If you do not specify namespace, Ruby starts from current namespace and works its way up to find the class, and because the namespaced class is not autoloaded yet, the ::DocumentPresenter
is found and autoloader does not trigger.
作为解决方案,我建议将 :: DocumentPresenter
重命名为 DocumentPresenterBase
,因为当您忘记命名空间或明确要求某个地方时,这可以保护您免受错误的侵害。
As a solution I would recommend renaming ::DocumentPresenter
to DocumentPresenterBase
, because this protects you from bugs when you forget namespacing or explicit requiring somewhere.
要考虑的第二个选项实际上是使用特定的命名空间的类名全部
The second option to consider would actually be using specific namespaced classnames all over the place, but this suffers from bugs when you accidentally forget to namespace some call.
class Guest::DocumentsController < ActionController::Base
def show
Guest::DocumentPresenter.new(find_document)
end
end
第三种选择是您的第二个选择-明确要求事先在初始化器中使用所有类。我已经用Rails API做到了这一点,该API在 JSON
中接收嵌入式模型,并且当尚未加载实际模型时,Rails倾向于为其命名空间。
Third option would be your second - explicitly require all the classes in initializer beforehand. I have done this with Rails API which receives embedded models in JSON
and Rails tends to namespace them when the actual models are not loaded yet.
选项3.5 您可能会欺骗自动装带器来完成繁重的工作(尽管,这似乎更像是黑客):
Option 3.5 You could probably trick autoloader to do the heavy lifting (though, this might seem more like a hack):
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
最干净的方法是重命名基类。
Still the cleanest would be to rename the base class.
这篇关于当加载根名称空间中的另一个同名类时,Rails类的加载会跳过命名空间类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!