2008-11-27 8 views
5

Hãy tưởng tượng bạn có một foo.rb thực thi, với các thư viện bar.rb đặt ra theo cách sau đây:Tìm thư viện tương đối khi sử dụng liên kết tượng trưng đến ruby ​​thực thi

<root>/bin/foo.rb 
<root>/lib/bar.rb 

Trong phần đầu của foo.rb bạn đặt sau đây yêu cầu phải có chức năng trong bar.rb:

require File.dirname(__FILE__)+"../lib/bar.rb" 

Điều này hoạt động tốt miễn là tất cả các cuộc gọi đến foo.rb đều trực tiếp. Nếu bạn đặt $ HOME/project và symlink foo.rb thành $HOME/usr/bin, thì __FILE__ giải quyết thành $HOME/usr/bin/foo.rb và do đó không thể định vị được bar.rb liên quan đến tên đệm cho foo.rb.

Tôi nhận thấy rằng các hệ thống đóng gói như rubygems khắc phục điều này bằng cách tạo không gian tên để tìm kiếm thư viện và cũng có thể điều chỉnh load_path bằng cách sử dụng $: để bao gồm $HOME/project/lib, nhưng dường như giải pháp đơn giản hơn hiện hữu. Có ai có kinh nghiệm với vấn đề này và tìm thấy một giải pháp hay công thức hữu ích?

Trả lời

11

Tôi biết đây là lứa tuổi già, nhưng tôi chỉ thấy điều này:

require 'pathname' 
APP_ROOT = File.join(File.dirname(Pathname.new(__FILE__).realpath),'..') 
+0

Điều đó chắc chắn tốt hơn, ít nhất nó chỉ là hai dòng. Vẫn không may là không có một giải pháp duy nhất. – dgtized

2

Bạn có thể sử dụng chức năng này để làm theo bất kỳ liên kết tượng trưng và trở về đường dẫn đầy đủ của tập tin thực:

def follow_link(file) 
    file = File.expand_path(file) 

    while File.symlink?(file) 
    file = File.expand_path(File.readlink(file), File.dirname(file)) 
    end 

    file 
end 

puts follow_link(__FILE__) 
+0

Tôi cho rằng nó hoạt động. Không thực sự là một giải pháp hạnh phúc cho một cái gì đó được cho là yêu cầu đầu tiên trong tập tin. Tôi không hài lòng với giải pháp bao gồm đoạn mã đó trong mọi tệp để tìm vị trí của chúng tôi. – dgtized

1

Có lẽ đáng nói đến là + hoạt động độc đáo với các đối tượng Pathname và cũng có phương pháp Kernel.Pathname, vì vậy mã ban đầu của @ Burke có thể được thực hiện ngắn hơn nữa:

require 'pathname' 
APP_ROOT = Pathname.new(__FILE__).realpath + "../../lib"