当加载根名称空间中的另一个同名类时,Rails类的加载会跳过命名空间类 [英] Rails class loading skips namespaced class when another class of same name in root namespace is loaded

查看:110
本文介绍了当加载根名称空间中的另一个同名类时,Rails类的加载会跳过命名空间类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个命名空间,每个命名空间都有自己的控制器和演示者类:
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类的加载会跳过命名空间类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆