为什么Ruby 1.9.2删除“。” 从LOAD_PATH,还有什么选择?


154

Ruby 1.9.2的最新变更集不再使当前目录.成为您的的一部分LOAD_PATH。我有大量的Rakefiles假定.是Rakefile的一部分LOAD_PATH,所以这使它们中断了(它们报告说,所有基于项目路径的require语句都“没有要加载的文件”)。是否有这样做的特殊理由?

至于修复,$: << "."在任何地方添加都可以,但是似乎难以置信,我不想这样做。使我的Rakefiles 1.9.2+兼容的首选方法是什么?

Answers:


141

它被认为是“安全”风险。

您可以使用绝对路径绕过它

File.expand_path(__FILE__) et al

或做

require './filename' (ironically).

或使用

require_relative 'filename'

或添加“包含”目录

ruby -I . ...

或相同,使用irb;

$irb -I .

27
我用完了require_relative。谢谢。
约翰·费米内拉

11
这是否类似于大多数Unix,但在运行可执行文件的路径中不包括当前目录?
安德鲁·格林

5
require './filename'仅当您的脚本是在将工作目录设置为脚本所在的目录的情况下执行时才起作用。在多目录项目中通常不是这种情况。
mxcl 2012年

34

有两个原因:

  • 健壮性和
  • 安全

两者都基于相同的基本原理:通常,运行代码时,您根本不知道当前目录是什么。这意味着,当您需要一个文件并依赖于该文件位于当前目录中时,您将无法控制该文件甚至存在于该文件中,还是您实际上希望该文件存在于该文件中。


5
我认为强制两个文件相对于彼此位于同一位置并不是必须的。如果这是真的,那么我们将没有用到目录。
约翰·费米内拉

4
@John Feminella:这与将文件放置在彼此相对的路径中有什么关系?问题在于将它们相对于.,即当前工作目录。如果用户cd进入另一个目录,则当前的工作目录会更改,并且您现在将require 完全不同,这取决于用户调用脚本时所在的目录。我认为这不是一个好主意。
约尔格W¯¯米塔格

因此,要保持一个体面的界面,您应该这样做吗?$: << File.dirname(__FILE__)
约书亚脸颊

4
@Joshua Cheek:就我个人而言,我不喜欢这样。(但是请不要看我的旧代码,因为它充满了诸如此类的东西:-))。我只是假装lib目录上$LOAD_PATH,然后require相对于所有文件lib。换句话说:我将其留给管理员来确定如何$LOAD_PATH正确设置。如果您使用RubyGems,那将是微不足道的,因为RubyGems会自动您执行此操作,并且如果您使用Debian软件包,那么这就是软件包维护者的工作。总而言之,它看起来效果很好。
约尔格W¯¯米塔格

8
@Joshua颊:另外,作为抗衡一个排序的,以去除.$LOAD_PATH,红宝石1.9.2介绍require_relative这... ...惊讶require相对于当前正在执行的文件的位置SA文件(即,相对于File.dirname(__FILE__))。
约尔格W¯¯米塔格

16

正如其他答案所指出的那样,这存在安全隐患,因为.在您的加载路径中引用的是当前工作目录Dir.pwd,而不是当前正在加载的文件的目录。因此,执行脚本的任何人都可以仅通过cd转到另一个目录来更改此设置。不好!

我一直在使用从构建的完整路径__FILE__作为替代。

require File.expand_path(File.join(File.dirname(__FILE__), 'filename'))

与不同的是require_relative,它与Ruby 1.8.7向后兼容。


4
还有这种变化(我个人觉得更容易理解):require Pathname.new(__FILE__).dirname + 'filename'
泰勒·里克

8

require_relative 'file_to_require'

将此内容放入代码中以使1.8.7中的require_relative工作:

unless Kernel.respond_to?(:require_relative)
  module Kernel
    def require_relative(path)
      require File.join(File.dirname(caller.first), path.to_str)
    end
  end
end


3

我发现这是一个令人困惑的变化,直到我意识到两件事。

您可以在.profile(Unix)中设置RUBYLIB,然后像以前一样继续进行:

export RUBYLIB="."

但是如上所述,长期以来,这样做一直被认为是不安全的。

在绝大多数情况下,您可以通过简单地在Ruby脚本前加上“'”来避免问题。例如./scripts/server。


3

正如JörgW Mittag指出的那样,我认为您要使用的是require_relative所需的文件相对于require声明的源文件,而不是当前的工作目录。

您的依赖关系应相对于rake构建文件。

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.