如何在Rails中相关的require,require_dependency和常量重新加载?

时间:2009-09-21 22:33:32

标签: ruby-on-rails require

requirerequire_dependency有何不同?
require_dependency如何在开发中自动重新加载类,但require不能?

我深入研究了Rails的ActiveSupport::Dependencies和dispatcher.rb代码。我在require_dependency代码中看到的是它基本上将常量添加到autoloaded_constants数组中。但是在每个请求之后,它会在clear_application内部调度程序中清除。

有人可以给出明确的解释或指出一些有用的资源吗?

2 个答案:

答案 0 :(得分:117)

require(及其堂兄load)是核心Ruby方法。 require_dependency是一种帮助Rails处理依赖关系管理问题的方法。简而言之,它允许Rails在开发模式下重新加载类,这样您每次进行代码更改时都不必重新启动服务器。 Rails框架将require_dependency您的代码,以便在进行更改时可以跟踪和重新加载它。标准Ruby require不会这样做。作为应用程序(或插件/引擎)开发人员,您不必担心require_dependency,因为这纯粹是Rails内部的。

Rails类加载过程的神奇之处在于ActiveSupport :: Dependencies模块。此代码扩展了默认的Ruby行为,允许Rails应用程序内的代码使用Rails的路径和文件命名约定自动加载模块(包括继承自Module的类)。这样就不需要程序员使用require调用来丢弃他们的代码,就像在普通的Ruby应用程序中一样。

换句话说,这可以让您在文件class Admin::User中定义app/models/admin/user.rb并让Rails知道您从应用程序的其他部分调用Admin::User.new时所说的内容一个控制器。如果不涉及ActiveSupport :: Dependencies,您必须手动require所需的一切。

如果您来自C#,Java等静态类型语言,那么这可能是一个惊喜:Rails代码在需要之前不会加载。例如,未定义User模型类,并且在您尝试调用user.rb之后才会加载User.whatever_method_here。 Rails阻止Ruby抱怨缺少的常量,加载User的代码,然后允许Ruby正常继续。

虽然我无法满足您的特定需求,但如果您确实需要在插件或引擎中使用require_dependency方法,我会感到非常惊讶。如果你遵循Rails约定,你也不必手动调整$ LOAD_PATH。这不是“Rails方式”。

在Ruby和Rails的世界里,简洁和清晰是关键。如果您只想写一个插件或引擎,并且您已经深入内部,那么您可以考虑从不同的角度处理您的问题。我的直觉告诉我,你可能正在尝试做一些不必要的复杂事情。但话说回来,我完全不清楚你在做什么! :)

答案 1 :(得分:19)

当您想要重新打开未在引擎中定义的类(例如在其他引擎或Rails应用程序中)并重新加载时,

require_dependency在引擎中很有用。在这种情况下,这样的工作:

# app/controllers/my_engine/documents_controller.rb
require_dependency MyEngine::Engine.root.join('app', 'controllers', 'my_engine', 'documents_controller').to_s

module MyEngine
  class DocumentsController
    def show
      render :text => 'different'
    end
  end
end