Rails 中的 require、require_dependency 和常量重载有啥关系?

Posted

技术标签:

【中文标题】Rails 中的 require、require_dependency 和常量重载有啥关系?【英文标题】:How are require, require_dependency and constants reloading related in Rails?Rails 中的 require、require_dependency 和常量重载有什么关系? 【发布时间】:2010-11-30 05:52:17 【问题描述】:

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

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

谁能给我一个明确的解释或指出一些有帮助的资源?

【问题讨论】:

仅供参考:类重新加载在引擎中自动处理(只不过是带有 app/ 文件夹的插件),就像它们在普通应用中一样。 谢谢,是的,我知道这一点。但这又引出了我的另一个问题:我可以在我的插件中使用其他插件吗?比如说,我想在自己的插件中使用 act_as_xxx 插件,我可以将 act_as_xxx 放在插件的供应商/插件目录中,然后将路径添加到 $LOAD_PATH 吗?我想我应该在另一个线程中问这个问题,这与我原来的问题无关。 【参考方案1】:

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

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

换句话说,这让您可以在文件app/models/admin/user.rb 中定义class Admin::User,并且当您从应用程序的另一部分(如控制器)调用Admin::User.new 时,Rails 会知道您在说什么。如果不涉及 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 的世界中,简单明了是关键。如果您只想编写一个插件或引擎,并且您已经深入研究了内部结构,那么您可以考虑从不同的角度解决您的问题。我的直觉告诉我,您可能正在尝试做一些不必要的复杂事情。但话又说回来,我不知道你在做什么! :)

【讨论】:

【参考方案2】:

require_dependency 在您想要重新打开引擎中未定义的类(例如在另一个引擎或 Rails 应用程序中)并重新加载它时在引擎中很有用。在这种情况下,这样的事情有效:

# 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

【讨论】:

以上是关于Rails 中的 require、require_dependency 和常量重载有啥关系?的主要内容,如果未能解决你的问题,请参考以下文章

Rails:备份mysql数据库脚本

如何在 Rails 中正确使用 params.require

在 Rails 4 中,`params.require(:person).permit(:name, :age)` 是做啥的?

在 Rails 3 应用程序中使用 require_dependency 对性能有何影响?

Rails动态params.require(...)。permit(...)语法?

markdown Rails Asset Pipeline:`require`指令