7

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

两个演示者都继承自::DocumentPresenter.

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

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

这通常会在同一命名空间中调用演示者。但是有时在开发环境中我看到 base :: DocumentPresenter 正在被使用。

我怀疑原因是 base ::DocumentPresenter 已经加载,因此 Rails 类自动加载不会费心再看。有可能是这种情况吗?它也可以在生产环境中发生吗?

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

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

有更好的解决方案吗?

4

2 回答 2

3

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

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

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

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

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

选项 3.5您可能会欺骗自动加载器来完成繁重的工作(尽管这看起来更像是一种 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 

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

于 2012-11-05T16:45:58.847 回答
1

我认为如果您想使用名称,在 3 个解决方案中,一个是您的第二个解决方案。

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

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

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

3)在初始化目录上创建一个文件并手动执行要求(最糟糕的选择:S)

于 2012-11-05T16:47:07.070 回答