2010-05-24 25 views
154

Các thay đổi mới nhất đối với Ruby 1.9.2 không còn làm cho thư mục hiện tại . một phần của số LOAD_PATH của bạn nữa. Tôi có một số lượng nhỏ các Rakefile giả định rằng . là một phần của LOAD_PATH, do đó, điều này đã phá vỡ chúng (chúng báo cáo "không có tệp như vậy để tải" cho tất cả các yêu cầu báo cáo dựa trên đường dẫn dự án). Có lý do cụ thể nào để làm việc này không?Tại sao Ruby 1.9.2 xóa "." từ LOAD_PATH và giải pháp thay thế là gì?

Để khắc phục, hãy thêm $: << "." ở mọi nơi, nhưng có vẻ vô cùng khó khăn và tôi không muốn làm điều đó. Cách ưa thích để làm cho Rakefiles 1.9.2+ của tôi tương thích là gì?

Trả lời

139

Nó được coi là một nguy cơ "bảo mật".

Bạn có thể khắc phục nó bằng cách sử dụng đường dẫn tuyệt đối

File.expand_path(__FILE__) et al 

hoặc làm

require './filename' (ironically). 

hoặc bằng cách sử dụng

require_relative 'filename' 

hoặc thêm một "bao gồm" thư mục

ruby -I . ... 

hoặc giống nhau, sử dụng irb;

$irb -I . 
+26

Tôi vết thương lên sử dụng 'require_relative'. Cảm ơn. –

+11

Điều này giống như hầu hết các bản sao không bao gồm thư mục hiện tại trong đường dẫn để chạy tệp thi hành? –

+1

@Andrew vâng tôi nghĩ vậy. – rogerdpack

34

Có hai lý do:

  • mạnh mẽ và
  • an ninh

Cả hai đều dựa trên nguyên tắc cơ bản giống nhau: nói chung, bạn chỉ có thể không biết những gì thư mục hiện hành là , khi mã của bạn được chạy. Điều đó có nghĩa rằng, khi bạn yêu cầu một tệp và phụ thuộc vào nó nằm trong thư mục hiện tại, bạn không có cách nào kiểm soát xem tệp đó sẽ có ở đó hay không, hoặc đó là tệp mà bạn thực sự mong đợi ở đó.

+5

Tôi không nghĩ rằng việc thực thi hai tệp đó ở cùng một vị trí tương đối với nhau phải là một yêu cầu không tốt. Nếu đó là sự thật, thì chúng tôi sẽ không sử dụng cho các thư mục. –

+4

@ John Feminella: điều này có liên quan gì đến việc đặt các tệp trong đường dẫn tương đối với nhau? Câu hỏi đặt ra là đặt chúng liên quan đến '.', tức là thư mục làm việc hiện tại. Nếu người dùng 'cd' vào một thư mục khác, thư mục làm việc hiện tại thay đổi, và bây giờ bạn' require' * hoàn toàn * các tệp khác nhau tùy thuộc vào thư mục mà người dùng đã gặp phải khi anh ta gọi kịch bản của bạn. Tôi không nghĩ đó là một ý hay. –

+0

Vì vậy, để duy trì một giao diện phong nha, bạn nên làm điều này? '$: << File.dirname (__ FILE __)' –

3

Như Jörg W Mittag đã chỉ ra, tôi nghĩ những gì bạn muốn sử dụng là require_relative do đó tệp bạn yêu cầu có liên quan đến tệp nguồn khai báo require chứ không phải là thư mục làm việc hiện tại.

Phụ thuộc của bạn phải liên quan đến tệp xây dựng rake của bạn.

16

Khi người khác trả lời, đó là rủi ro bảo mật vì . trong đường dẫn tải của bạn đề cập đến thư mục làm việc hiện tại Dir.pwd, không phải thư mục của tệp hiện đang được tải. Vì vậy, bất kỳ ai đang thực thi tập lệnh của bạn đều có thể thay đổi điều này đơn giản bằng cách cd nhập vào một thư mục khác. Không tốt!

Tôi đã sử dụng đường dẫn đầy đủ được xây dựng từ __FILE__ làm phương án thay thế.

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

Không giống như require_relative, tính năng này tương thích ngược với Ruby 1.8.7.

+4

Cũng có biến thể này (mà cá nhân tôi tìm thấy dễ đọc hơn): 'yêu cầu Pathname.new (__ FILE __). Dirname + 'filename'' –

3

Tôi nhận thấy đây là một thay đổi gây nhầm lẫn cho đến khi tôi nhận ra một vài điều.

Bạn có thể đặt RUBYLIB trong .profile của bạn (Unix) và tiếp tục cuộc sống như bạn đã làm trước đây:

export RUBYLIB="."

Nhưng như đã đề cập ở trên, nó từ lâu đã được coi là không an toàn để làm như vậy.

Đối với phần lớn các trường hợp, bạn có thể tránh các sự cố bằng cách chỉ cần gọi các tập lệnh Ruby của bạn bằng một phần tử được thêm trước '.' ví dụ. ./scripts/server.

8

Sử dụng require_relative 'file_to_require'

Ném này trong mã của bạn để làm cho công việc require_relative trong 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 
Các vấn đề liên quan