在Ruby中require_relative和require有什么区别?
在Ruby中require_relative
和require
什么区别?
只要看看文档 :
require_relative
通过允许您加载与包含require_relative
语句的文件相关的文件来补充内置方法require
。例如,如果在“test”目录中有单元测试类,而在测试“test / data”目录下有它们的数据,则可以在测试用例中使用这样的一行:
require_relative "data/customer_data_1"
从Ruby API :
require_relative通过允许您加载与包含require_relative语句的文件相关的文件来补充内置方法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找到这个文档;
require_relative
是require
一个方便的子集
require_relative('path')
等于:
require(File.expand_path('path', File.dirname(__FILE__)))
如果__FILE__
被定义,否则会引发LoadError
。
这意味着:
-
require_relative 'a'
和require_relative './a'
要求相对于当前文件 (__FILE__
)。这是你要在库中需要的时候使用的,因为你不希望结果依赖于调用者的当前目录。
-
eval('require_relative("a.rb")')
引发LoadError
因为__FILE__
没有在eval
定义。这就是为什么你不能在RSpec测试中使用
require_relative
来获得eval
。
以下操作仅适用于require
:
-
require './a.rb'
需要相对于当前目录 -
require 'a.rb'
使用搜索路径($LOAD_PATH
)来要求。 它没有找到相对于当前目录或路径的文件。这对于
require_relative
来说是不可能的,因为文档说路径搜索只发生在“文件名不能解析为绝对路径”时(即以/
或./
或../
开头),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__
require
使用当前正在运行该程序的目录
require_relative
使用该程序本身所在的目录
例如,如果一个程序在~/code
并且被称为1.rb
并且你已经完成了一个cd到那个目录
cd ~/code
你尝试运行ruby程序
ruby 1.rb
然后在1.rb
之内
require './2.rb' require_relative '3.rb'
两者都会工作。
但是,如果你在另一个目录,说
cd ~/tmp
并尝试使用该程序运行
ruby ../1.rb
那么你会得到一个错误,如
/home/durrantm/.rvm/rubies/ruby-2.1.2/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:54:in `require': cannot load such file -- ./2.rb (LoadError) from /home/durrantm/.rvm/rubies/ruby-2.1.2/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:54:in `require' from ../1.rb:1:in `<main>'
当试图使用
require './2.rb'
而使用
require_relative '3.rb'
仍然工作正常_因为引用( 3.rb
)是相对于程序( 1.rb
)所在的目录。
我刚刚看到RSpec的代码对require_relative
是O(1)常量并且require
是O(N)线性有一些评论。 所以可能的区别是, require_relative
是比require
的首选。
最好的答案是正确的,但技术性很强。 对于那些更新的红宝石 –
-
require_relative
将很可能用于从您编写的另一个文件引入代码。
例如,如果你在~/my-project/data.rb
有数据,而你想把它包含在~/my-project/solution.rb
呢? 在solution.rb
您将添加require_relative 'data'
。
注意这些文件不需要在同一个目录中是很重要的。 require_relative '../../folder1/folder2/data'
也是有效的。
-
require
很可能被用来从别人写的库中引入代码。
例如,如果您想使用active_support
库中提供的辅助函数之一,该怎么办? 您需要使用gem install activesupport
来安装gem,然后在文件gem install activesupport
require 'active_support'
。
require 'active_support/all' "FooBar".underscore
换言之,
-
require_relative
需要一个特别指向相对于调用它的文件的文件。 -
require
需要包含在$ LOAD_PATH中的文件。
我想补充一点,在使用windows时,如果脚本是本地运行的,或者从映射的网络驱动器运行,但是从UNC \ servername \ sharename \文件夹路径运行,则require './1.rb'
使用require './1.rb'
require_relative './1.rb'
我不会在讨论中require_relative './1.rb'
其他原因。