2009-04-25 19 views
51

Có cách nào ngắn hơn để yêu cầu tệp nằm trong cùng một thư mục (khi tập lệnh đang được thực hiện) không?Có cách nào ngắn hơn để yêu cầu một tệp trong cùng một thư mục trong ruby ​​không?

require File.expand_path(File.dirname(__FILE__) + '/some_other_script') 

Tôi đọc mà require "my_script"require "./my_script" thực sự sẽ được tải kịch bản hai lần (ruby sẽ không nhận ra rằng nó thực sự là kịch bản giống nhau), và đây là lý do tại sao File.expand_path được đề nghị: nếu nó được sử dụng mỗi khi script là bắt buộc, sau đó nó sẽ chỉ được nạp một lần.

Có vẻ lạ với tôi rằng một ngôn ngữ ngắn gọn như Ruby dường như không có giải pháp ngắn hơn. Ví dụ, python chỉ đơn giản là có này:

import .some_other_module_in_the_same_directory 

Tôi đoán tôi có thể khỉ vá require ... nhưng đó chỉ là ác! ;-)

Trả lời

2

Ở trên sẽ hoạt động ngay cả khi bạn đang chạy tập lệnh từ một số thư mục khác. Tuy nhiên, bên trong cùng một thư mục các biểu mẫu ngắn hơn bạn đề cập đến hoạt động như mong đợi và ít nhất là cho ruby ​​1.9 sẽ không dẫn đến yêu cầu kép.

testa.rb

puts "start test A" 
require 'testb' 
require './testb' 
puts "finish test A" 

testb.rb

puts "start test B" 
puts "finish test B" 

chạy 'ruby testa.rb' sẽ cho kết quả:

start test A 
start test B 
finish test B 
finish test A 

Tuy nhiên, hình thức còn sẽ làm việc thậm chí từ một thư mục khác (ví dụ: ruby ​​somedir/script.rb)

2

Đặt điều này trong một thư mục thư viện chuẩn (một nơi nào đó đã có trong loadpath mặc định của bạn $:):

# push-loadpath.rb 
if caller.first 
    $: << File.expand_path(File.dirname(caller.first)) 
end 

Sau đó, điều này sẽ làm việc

% ls /path/to/ 
bin.rb lib1.rb lib2.rb #... 
% cat /path/to/bin.rb 
load 'push-loadpath.rb' 
require 'lib1' 
require 'lib2' 
#... 

caller cung cấp cho bạn truy cập vào các callstack hiện nay, và nói bạn những gì tập tin và ở đâu, vì vậy push-loadpath.rb sử dụng đó để thêm các tập tin mà load 'd nó vào loadpath.

Lưu ý rằng bạn nên load tệp, thay vì require, để cơ thể có thể được gọi nhiều lần (một lần cho mỗi lần bạn muốn thay đổi đường dẫn tải).

Cách khác, bạn có thể bọc cơ thể trong một phương pháp,

# push-loadpath.rb 
def push_loadpath 
    $: << File.expand_path(File.dirname(caller.first)) 
end 

này sẽ cho phép bạn require nó, và sử dụng nó theo cách này:

% ls /path/to/ 
bin.rb lib1.rb lib2.rb #... 
% cat /path/to/bin.rb 
require 'push-loadpath' 
push_loadpath 
require 'lib1' 
require 'lib2' 
#... 
11

Chỉ cần filename.

Có, nó sẽ nhập hai lần nếu bạn chỉ định nó là filename./filename, vì vậy đừng làm điều đó. Bạn không chỉ định số .rb, vì vậy đừng chỉ định đường dẫn.Tôi thường đặt phần lớn các ứng dụng logic của tôi vào một tập tin trong lib, và sau đó có một kịch bản trong bin mà trông giống như sau:

#!/usr/bin/env ruby 

$: << File.join(File.dirname(__FILE__), "/../lib") 
require 'app.rb' 
App.new.run(ARGV) 

Một lợi thế là tôi tìm thấy nó dễ dàng hơn để làm kiểm tra đơn vị nếu việc bốc logic ứng dụng không tự động bắt đầu thực hiện nó.

83

Vì ruby ​​1.9 bạn có thể sử dụng require_relative.

+0

Ôi trời, ước gì tôi đã thấy câu trả lời của bạn trước đó. –

Các vấn đề liên quan