本文翻译自:What is the difference between require_relative and require in Ruby?
Ruby中的require_relative
和require
什么区别?
#1楼
参考:https://stackoom.com/question/FPPG/Ruby中的require-relative和require有什么区别
#2楼
I just saw the RSpec's code has some comment on require_relative
being O(1) constant and require
being O(N) linear. 我只是看到RSpec的代码对require_relative
为O(1)常数和require
为O(N)线性有一些评论。 So probably the difference is that require_relative
is the preferred one than require
. 所以可能的区别是, require_relative
是比require
首选的一个。
#3楼
require_relative
is a convenient subset of require
require_relative
是require
的便捷子集
require_relative('path')
equals: 等于:
require(File.expand_path('path', File.dirname(__FILE__)))
if __FILE__
is defined, or it raises LoadError
otherwise. 如果定义了__FILE__
,否则引发LoadError
。
This implies that: 这意味着:
require_relative 'a'
andrequire_relative './a'
require relative to the current file (__FILE__
). 与当前文件 (__FILE__
)相关的require_relative './a'
require_relative 'a'
和require_relative './a'
。This is what you want to use when requiring inside your library, since you don't want the result to depend on the current directory of the caller. 这是在库中需要时要使用的内容,因为您不希望结果依赖于调用者的当前目录。
eval('require_relative("a.rb")')
raisesLoadError
because__FILE__
is not defined insideeval
.eval('require_relative("a.rb")')
引发LoadError
因为在eval
未定义__FILE__
。This is why you can't use
require_relative
in RSpec tests, which geteval
ed. 这就是为什么不能在已eval
RSpec测试中使用require_relative
原因。
The following operations are only possible with require
: 以下操作仅可通过require
:
require './a.rb'
requires relative to the current directoryrequire './a.rb'
相对于当前目录的要求require 'a.rb'
uses the search path ($LOAD_PATH
) to require.require 'a.rb'
使用搜索路径($LOAD_PATH
)进行要求。 It does not find files relative to current directory or path. 它找不到相对于当前目录或路径的文件。This is not possible with
require_relative
because the docs say that path search only happens when "the filename does not resolve to an absolute path" (ie starts with/
or./
or../
), which is always the case forFile.expand_path
. 这对于require_relative
是不可能的,因为文档说仅当“文件名不能解析为绝对路径”(即以/
或./
或../
开头)时才进行路径搜索,而File.expand_path
总是这样。
The following operation is possible with both, but you will want to use require
as it is shorter and more efficient: 两者都可以进行以下操作,但是您需要使用require
因为它更短,更有效:
-
require '/a.rb'
andrequire_relative '/a.rb'
both require the absolute path.require '/a.rb'
和require_relative '/a.rb'
都需要绝对路径。
Reading the source 阅读源
When the docs are not clear, I recommend that you take a look at the sources (toggle source in the docs). 如果文档不清楚,建议您查看源代码(在文档中切换源代码)。 In some cases, it helps to understand what is going on. 在某些情况下,它有助于了解发生了什么。
require: 要求:
VALUE rb_f_require(VALUE obj, VALUE fname) {
return rb_require_safe(fname, rb_safe_level());
}
require_relative: 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());
}
This allows us to conclude that 这使我们得出结论:
require_relative('path')
is the same as: 是相同的:
require(File.expand_path('path', File.dirname(__FILE__)))
because: 因为:
rb_file_absolute_path =~ File.expand_path
rb_file_dirname1 =~ File.dirname
rb_current_realfilepath =~ __FILE__
#4楼
Summary 摘要
Use require
for installed gems 已安装宝石的使用require
Use require_relative
for local files 对本地文件使用require_relative
require
uses your $LOAD_PATH
to find the files. require
使用$LOAD_PATH
查找文件。 require_relative
uses the current location of the file using the statement require_relative
通过以下语句使用文件的当前位置
require 要求
Require relies on you having installed (eg gem install [package]
) a package somewhere on your system for that functionality. Require依赖于您已在系统中某个位置gem install [package]
了某个gem install [package]
(例如gem install [package]
)以实现该功能。
When using require
you can use the " ./
" format for a file in the current directory, eg require "./my_file"
but that is not a common or recommended practice and you should use require_relative
instead. 使用require
, 可以为当前目录中的文件使用“ ./
”格式,例如require "./my_file"
但这不是常见的或推荐的做法,而应使用require_relative
。
require_relative require_relative
This simply means include the file 'relative to the location of the file with the require_relative statement'. 这仅意味着将文件“相对于文件的位置并带有require_relative语句”。 I generally recommend that files should be "within" the current directory tree as opposed to "up", eg don't use 我通常建议文件应位于当前目录树中,而不要位于“当前目录树”中,例如不要使用
require_relative '../../../filename'
(up 3 directory levels) within the file system because that tends to create unnecessary and brittle dependencies. 文件系统中最多3个目录级别),因为这往往会创建不必要和脆弱的依赖关系。 However in some cases if you are already 'deep' within a directory tree then "up and down" another directory tree branch may be necessary. 但是,在某些情况下,如果您已经“深入”目录树,则可能需要“向上和向下”另一个目录树分支。 More simply perhaps, don't use require_relative for files outside of this repository (assuming you are using git which is largely a de-facto standard at this point, late 2018). 更简单的也许是, 不要对该存储库之外的文件使用require_relative (假设您正在使用git,这在很大程度上是事实上的标准,即2018年底)。
Note that require_relative
uses the current directory of the file with the require_relative statement (so not necessarily your current directory that you are using the command from). 请注意, require_relative
将文件的当前目录与require_relative语句一起使用(因此,不一定要使用命令的当前目录)。 This keeps the require_relative
path "stable" as it always be relative to the file requiring it in the same way. 这使require_relative
路径始终“稳定”,因为它始终以相同的方式相对于需要它的文件而言。
#5楼
我想补充一点,如果脚本是在本地运行或从映射的网络驱动器运行,则在使用Windows时可以使用require './1.rb'
,但是从UNC \\ servername \\ sharename \\ folder路径运行时,则需要使用require_relative './1.rb'
,由于其他原因,我不会参与讨论。
#6楼
Just look at the docs : 只要看一下文档 :
require_relative
complements the builtin methodrequire
by allowing you to load a file that is relative to the file containing therequire_relative
statement.require_relative
通过允许您加载相对于包含require_relative
语句的文件的文件来补充内置方法require
。For example, if you have unit test classes in the "test" directory, and data for them under the test "test/data" directory, then you might use a line like this in a test case: 例如,如果您在“ test”目录中有单元测试类,而在“ test / data”目录中有它们的数据,那么在测试用例中可以使用如下代码:
require_relative "data/customer_data_1"