2009-04-25 11 views
51

Gibt es einen kürzeren Weg, um eine Datei im selben Verzeichnis zu benötigen (wie das Skript ausgeführt wird)?Gibt es eine kürzere Möglichkeit, eine Datei im selben Verzeichnis in Ruby zu verlangen?

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

ich gelesen, dass require "my_script" und require "./my_script" tatsächlich das Skript geladen werden zweimal (Rubin nicht erkennen, dass es eigentlich das gleiche Skript ist), und dies ist der Grund, warum File.expand_path empfohlen: wenn es jedes Mal, das verwendet wird, Skript ist erforderlich, dann wird es nur einmal geladen.

Es scheint mir komisch, dass eine knappe Sprache wie Ruby keine kürzere Lösung zu haben scheint. Zum Beispiel hat Python einfach:

import .some_other_module_in_the_same_directory 

Ich glaube, ich könnte Affen Patch require ... aber das ist nur böse! ;-)

Antwort

2

Das obige funktioniert auch, wenn Sie das Skript aus einem anderen Verzeichnis ausführen. Innerhalb des gleichen Verzeichnisses funktionieren die kürzeren Formulare, auf die Sie verweisen, jedoch wie erwartet und ergeben zumindest für Ruby 1.9 keine doppelte Anforderung.

testa.rb

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

testb.rb

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

'Rubin testa.rb' läuft bewirkt:

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

jedoch die längere Form auch funktionieren aus einem anderen Verzeichnis (z. B. ruby ​​somedir/script.rb)

2

Setzen Sie diese in einem Standard-Bibliotheksverzeichnis (irgendwo, dass $: bereits in Ihrem Standard-Lastweg ist):

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

Dann sollte dies

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

caller können Sie auf der aktuellen Aufrufliste zuzugreifen, und erzählt Sie, welche Datei und wo, so push-loadpath.rb verwendet, um die Datei, die load 'd es zum loadpath hinzuzufügen.

Beachten Sie, dass Sie load die Datei lieber als require es, so dass der Körper mehrmals aufgerufen werden kann (einmal für jedes Mal, wenn Sie den Ladepfad ändern möchten).

Alternativ können Sie den Körper in einem Verfahren wickeln,

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

Dieses Sie es require erlauben würde, und es auf diese Weise verwenden:

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

gerade benötigen filename.

Ja, es wird zweimal importiert, wenn Sie es als filename und angeben, also tun Sie das nicht. Sie geben nicht .rb an, also geben Sie den Pfad nicht an.Ich habe in der Regel den Großteil meiner Anwendungslogik in eine Datei in lib, und haben dann ein Skript in bin, die etwa wie folgt aussieht:

#!/usr/bin/env ruby 

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

Ein weiterer Vorteil ist, dass ich es einfacher finden Unit-Tests zu tun, wenn die Lade Die Anwendungslogik startet die Ausführung nicht automatisch.

83

Seit Rubin 1.9 können Sie require_relative verwenden.

+0

Oh Gott, ich wünschte, ich hätte deine Antwort früher gesehen. –

Verwandte Themen