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

在Ruby中require_relativerequire什么区别?

只要看看文档 :

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_relativerequire一个方便的子集

 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'其他原因。