2010-05-24 76 views
154

Ruby 1.9.2的最新變更不再將當前目錄.作爲您的LOAD_PATH的一部分。我有一個不平凡的Rakefiles數量,假設.LOAD_PATH的一部分,所以這打破了他們(他們報告「沒有這樣的文件來加載」所有基於項目路徑的需求語句)。這樣做有沒有特別的理由?爲什麼Ruby 1.9.2刪除「。」來自LOAD_PATH,還有什麼替代方案?

至於一個修復,添加$: << "."無處不在,但似乎令人難以置信的哈​​克,我不想這樣做。什麼是使我的Rakefiles 1.9.2+兼容的首選方法?

回答

139

它被視爲「安全」風險。

您可以通過使用絕對路徑

File.expand_path(__FILE__) et al 

或做

require './filename' (ironically). 

或使用

require_relative 'filename' 

或將繞過它的 「include」 目錄

ruby -I . ... 

或相同,使用irb;

$irb -I . 
+26

我結束了使用'require_relative'。謝謝。 – 2010-05-24 22:50:56

+11

這是類似於大多數unixes不包括運行可執行文件的路徑中的當前目錄嗎? – 2010-05-24 23:56:31

+1

@Andrew是的,我認爲是。 – rogerdpack 2011-05-25 03:32:30

34

有兩個原因:

  • 魯棒性和
  • 安全

兩者都基於相同的基本原則:在一般情況下,你根本無法知道當前目錄是什麼,當你的代碼運行。這意味着,當你需要一個文件並依賴它在當前目錄中時,你無法控制該文件是否會存在,或者它是否是你真正希望存在的文件。

+5

我不認爲強制執行這兩個文件相對於彼此是相同的位置必然是一個不好的要求。如果那是真的,那麼我們就不會使用目錄。 – 2010-05-25 12:11:18

+4

@John Feminella:這與把文件放在相對路徑上有什麼關係?問題是關於把它們放在'.',即當前的工作目錄。如果用戶cd到不同的目錄中,當前的工作目錄會發生變化,並且您現在需要完全不同的文件,具體取決於用戶在調用腳本時碰巧遇到的目錄。我不認爲這是個好主意。 – 2010-05-25 12:53:42

+0

因此,要保持一個體面的界面,你應該這樣做? '$:<< File.dirname(__ FILE __)' – 2010-09-11 22:07:38

3

正如JörgW Mittag指出的那樣,我認爲您要使用的是require_relative,因此您需要的文件與require聲明的源文件相關,而不是當前工作目錄。

您的依賴關係應該與您的rake構建文件相關。

16

正如其他人指出的那樣,這是一個安全風險,因爲您的加載路徑中的.指的是當前工作目錄Dir.pwd,而不是當前正在加載的文件的目錄。所以執行腳本的人可以簡單地通過cd改變它到另一個目錄。不好!

我一直在使用從__FILE__構建的完整路徑作爲替代。與require_relative不同,它與Ruby 1.8.7向後兼容。

+4

也有這種變化(我個人發現它更具可讀性): 'require Pathname.new(__ FILE __)。dirname +'filename'' – 2011-05-06 23:12:18

3

我發現這是一個混淆的變化,直到我意識到一些事情。

你可以在你的.profile文件(UNIX)設置RUBYLIB和之前一樣生活下去:

export RUBYLIB="."

但正如上面提到的,它一直被認爲不安全的這樣做。

對於絕大多數情況,您可以通過簡單地用前綴'。'來調用Ruby腳本來避免問題。例如./scripts/server。

8

使用require_relative 'file_to_require'

拋出這個在你的代碼,以使require_relative工作1.8.7:

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