Ruby-on-rails Rails 中的 require、require_dependency 和常量重新加载有何关联?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1457241/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 21:47:23  来源:igfitidea点击:

How are require, require_dependency and constants reloading related in Rails?

ruby-on-railsrequire

提问by wei

How are requireand require_dependencydifferent?
How can require_dependencyautomatically reload classes in development but requirecan't ?

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

I digged into Rails' ActiveSupport::Dependenciesand dispatcher.rb code. What I saw in require_dependency's code is it basically adds the constants to an autoloaded_constantsarray. But it gets cleared in clear_applicationinside dispatcher after each request.

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

Can someone give a clear explanation or point me to some resources which will help?

有人可以给出明确的解释或向我指出一些有帮助的资源吗?

回答by MDaubs

require(and its cousin load) are core Ruby methods. require_dependencyis a method that helps Rails handle the problem of dependency management. Long story short, it allows Rails to reload classes in development mode so that you don't have to restart the server each time you make a code change. The Rails framework will require_dependencyyour code so that it can track and reload it when changes are made. The standard Ruby requiredoesn't do that. As an app (or plugin/engine) developer you should not have to worry about require_dependencyas this is purely internal to Rails.

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

The magic of the Rails class loading process is in the ActiveSupport::Dependencies module. This code extends the default Ruby behavior to allow code inside your Rails app to automatically load modules (including classes which inherit from Module) using Rails' path and file naming conventions. This eliminates the need for the programmer to litter their code with requirecalls like you would in a plain Ruby application.

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

To put it another way, this lets you define class Admin::Userinside the file app/models/admin/user.rband have Rails know what you are talking about when you call Admin::User.newfrom another part of the application like a controller. Without ActiveSupport::Dependencies involved you would have to manually requireeverything you needed.

换句话说,这让您可以class Admin::User在文件内部进行定义,app/models/admin/user.rb并让 Rails 在您Admin::User.new从应用程序的另一部分(如控制器)调用时知道您在说什么。如果不涉及 ActiveSupport::Dependencies,您将不得不手动完成require所需的一切。

If you are coming from a statically typed language like C#, Java, etc then this might be a surprise: Rails code is not loaded until it is needed. For example, a Usermodel class isn't defined and user.rbisn't loaded until AFTER you try to call User.whatever_method_here. Rails prevents Ruby from complaining about that missing constant, loads code for User, and then allows Ruby to continue as normal.

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

While I can't speak for your specific need, I would be very surprised if you actually needed to use the require_dependencymethod from within a plugin or engine. If you follow Rails conventions you shouldn't have to tweak the $LOAD_PATH by hand, either. This is not "the Rails way".

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

In the world of Ruby and also Rails simplicity and clarity is key. If all you want to do is write a plugin or engine and you are already diving deep into internals then you may consider approaching your problem from a different angle. My gut tells me that you may be trying to do something that is needlessly complicated. But then again, I have no clue what you are doing exactly!! :)

在 Ruby 和 Rails 的世界中,简单和清晰是关键。如果您只想编写一个插件或引擎,并且您已经深入研究内部结构,那么您可以考虑从不同的角度解决您的问题。我的直觉告诉我,您可能正在尝试做一些不必要的复杂事情。但是话又说回来,我不知道你到底在做什么!!:)

回答by Kris

require_dependencyis useful in an engine when you want to re-open a class which is not defined in your engine (for example in another engine or Rails app) and have it reloaded. In which case something like this works:

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