Ruby中的require_relative和require有什么区别?


302

require_relativerequireRuby有什么区别?


9
在1.9.2之前,不需要require_relative,因为脚本的当前目录在中$:。请参阅stackoverflow.com/questions/2900370
Nakilon 2010年

1
require_relative需要一个专门指向相对于调用它的文件的文件。require要求$ LOAD_PATH中包含一个文件。
多纳托

Answers:


298

只要看一下文档

require_relativerequire通过允许您加载相对于包含该require_relative语句的文件的文件来补充内置方法。

例如,如果您在“ test”目录中有单元测试类,而在“ test / data”目录中有它们的数据,那么在测试用例中可以使用如下代码:

require_relative "data/customer_data_1"

28
有没有之间的差异require './file.rb'require_relative 'file.rb'
Ciro Santilli郝海东冠状病六四事件法轮功

69
@CiroSantilli是的。require_relative允许您“加载相对于包含该require_relative语句的文件的文件 ”。随着require./表明相对于当前工作目录的路径。
Ajedi32

16
我认为更重要的一点是,require str始终将搜索$ LOAD_PATH中的目录。require_relative当需要加载的文件相对于需要加载的文件存在于某处时,应该使用。require为“外部”依赖项保留。
rthbound

97

require_relative 是一个方便的子集 require

require_relative('path')

等于:

require(File.expand_path('path', File.dirname(__FILE__)))

如果__FILE__定义了if ,否则引发LoadError

这意味着:

  • require_relative 'a'require_relative './a'要求相对于当前文件__FILE__)。

    这是在库中需要时要使用的内容,因为您不希望结果依赖于调用者的当前目录。

  • eval('require_relative("a.rb")')引发LoadError因为__FILE__在内部没有定义eval

    这就是为什么您不能require_relativeevaled的RSpec测试中使用的原因。

以下操作仅适用于require

  • require './a.rb'需要相对于当前目录

  • require 'a.rb'使用搜索路径($LOAD_PATH)要求。它找不到相对于当前目录或路径的文件。

    这是不可能的,require_relative因为文档说只有在“文件名不能解析为绝对路径”(即以/or ./或开头../)时才进行路径搜索,对于总是如此File.expand_path

两者都可以进行以下操作,但是您希望使用require它更短,更有效:

  • require '/a.rb'并且require_relative '/a.rb'都需要绝对路径。

阅读源代码

如果文档不清楚,建议您查看源代码(在文档中切换源代码)。在某些情况下,它有助于了解发生了什么。

要求:

VALUE rb_f_require(VALUE obj, VALUE fname) {
  return rb_require_safe(fname, rb_safe_level());
}

require_relative:

VALUE rb_f_require_relative(VALUE obj, VALUE fname) {
    VALUE base = rb_current_realfilepath();
    if (NIL_P(base)) {
        rb_loaderror("cannot infer basepath");
    }
    base = rb_file_dirname(base);
    return rb_require_safe(rb_file_absolute_path(fname, base), rb_safe_level());
}

这使我们得出结论:

require_relative('path')

是相同的:

require(File.expand_path('path', File.dirname(__FILE__)))

因为:

rb_file_absolute_path   =~ File.expand_path
rb_file_dirname1        =~ File.dirname
rb_current_realfilepath =~ __FILE__

74

从Ruby API中

require_relative通过允许您加载相对于包含require_relative语句的文件的文件来补充内置方法require。

使用require加载文件时,通常会访问系统中已正确安装且可访问的功能。require并不是在项目代码内加载文件的良好解决方案。这对于开发阶段,访问测试数据,甚至访问“锁定”在项目内部而不打算供外部使用的文件,可能都是有用的。

例如,如果您在“ test”目录中有单元测试类,而在“ test / data”目录中有它们的数据,那么在测试用例中可以使用如下代码:

require_relative "data/customer_data_1" 

由于“测试”和“测试/数据”都不可能出现在Ruby的库路径中(并且有充分的理由),因此通常的需求不会找到它们。require_relative是解决此特定问题的好方法。

您可以包括或忽略正在加载的文件的扩展名(.rb或.so)。

路径必须响应to_str。

您可以在http://extensions.rubyforge.org/rdoc/classes/Kernel.html上找到文档。


50

摘要

使用require已安装的宝石

使用require_relative本地文件

require使用您$LOAD_PATH来查找文件。
require_relative使用语句使用文件的当前位置


要求

Require取决于您已gem install [package]在系统中某处安装(例如)软件包以实现该功能。

使用时require可以./对当前目录中的文件使用“ ”格式,例如,require "./my_file"但这不是常见的或推荐的做法,应require_relative改为使用。

require_relative

这仅意味着将文件“相对于文件的位置并带有require_relative语句”。我通常建议文件应位于当前目录树中,而不要位于“目录”中,例如不要使用

require_relative '../../../filename'

(最多3个目录级别)文件系统中,因为这往往会创建不必要和脆弱的依赖关系。但是,在某些情况下,如果您已经“深入”目录树,则可能需要“向上和向下”另一个目录树分支。更简单的也许是,不要对存储库之外的文件使用require_relative(假设您正在使用git,这在很大程度上是事实上的标准,即2018年底)。

注意,该文件require_relative的当前目录与require_relative语句一起使用(因此不一定要使用命令的当前目录)。这样可以保持require_relative路径“稳定”,因为它始终以相同的方式相对于需要它的文件而言。


27

最佳答案是正确的,但技术性很强。对于那些较新的Ruby:

  • require_relative 将最有可能用于从您编写的另一个文件中引入代码。

例如,如果您有数据~/my-project/data.rb并想将其包含在其中,该~/my-project/solution.rb怎么办?在solution.rb您将添加require_relative 'data'

请务必注意,这些文件不必位于同一目录中。 require_relative '../../folder1/folder2/data'也有效。

  • require 将最有可能用于从别人编写的库中引入代码。

例如,如果要使用active_support库中提供的帮助程序功能之一怎么办?您需要使用安装Gem,gem install activesupport然后在文件中安装require 'active_support'

require 'active_support/all'
"FooBar".underscore

换句话说-

  • require_relative 需要一个专门指向相对于调用它的文件的文件。

  • require需要$LOAD_PATH。中包含的文件。


3
我该如何对这个答案进行投票,并将其一直带到顶部,以便该问题页面的每个访问者都可以立即获得清晰易懂的答案,而不会绞尽脑汁?
TiredOfProgramming

16

我只是看到RSpec的代码对require_relativeO(1)常量和requireO(N)线性有一些评论。因此,可能的区别在于,这require_relative是首选的require


1
有趣。我登陆这里寻找速度比较的信息。我的想法是require_relative更快,因为加载程序不必在搜索文件时遍历加载路径。本质上,require_relative提供了直接链接。
2015年

早期讨论require_relative速度和RSpec 更改日志
2015年

1

我想补充一点,在使用Windows时,可以使用require './1.rb'脚本是在本地运行还是从映射的网络驱动器运行,而从UNC \\servername\sharename\folder路径运行时则需要使用require_relative './1.rb'

我不会在讨论中混用其他原因。


我想知道如何加载require_relative文件,请您在这个stackoverflow.com/questions/43487784/…上
发表
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.