2009-04-25 7 views
51

Czy istnieje krótszy sposób na wymaganie pliku znajdującego się w tym samym katalogu (co wykonywany skrypt)?Czy istnieje krótszy sposób na żądanie pliku w tym samym katalogu w ruby?

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

czytałem że require "my_script" i require "./my_script" rzeczywiście załadować skrypt dwukrotnie (rubin nie będzie wiedział, że to jest rzeczywiście taki sam scenariusz) i to jest powód, dlaczego File.expand_path zaleca: jeśli jest on używany za każdym razem, skrypt jest wymagany, a następnie zostanie załadowany tylko raz.

Wydaje mi się dziwne, że zwięzły język, taki jak Ruby, nie wydaje się mieć krótszego rozwiązania. Na przykład, po prostu ma to pyton:

import .some_other_module_in_the_same_directory 

Chyba mogłem małpa poprawkę require ... ale to po prostu zły! ;-)

Odpowiedz

2

Powyższe działa, nawet jeśli uruchamiasz skrypt z innego katalogu. Jednak w tym samym katalogu krótsze formularze, o których mowa, działają zgodnie z oczekiwaniami, a przynajmniej dla rubinu 1.9 nie skutkują podwójnym żądaniem.

testa.rb

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

testb.rb

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

działa 'testa.rb Ruby' spowoduje:

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

Jednak im dłużej forma będzie działać nawet z innego katalogu (np. ruby ​​somedir/script.rb)

2

umieścić to w standardowym katalogu biblioteki (gdzieś, że znajduje się już w domyślnej loadpath $:):

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

Następnie, powinno to działać

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

caller daje dostęp do aktualnej callstack i mówi jaki plik i gdzie, więc push-loadpath.rb używa go do dodania pliku, który load "do ścieżki ładowania.

Zauważ, że powinieneś load plik, a nie require go, więc ciało może zostać wywołane wiele razy (raz za każdym razem, gdy chcesz zmienić ścieżkę ładowania).

Alternatywnie, można owinąć ciało w metodzie

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

Pozwoliłoby do require nim i używać go w ten sposób:

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

Wystarczy wymagać filename.

Tak, zostanie zaimportowany dwukrotnie, jeśli zostanie określony jako filename i ./filename, więc nie rób tego. Nie określasz wartości .rb, więc nie określaj ścieżki.I zazwyczaj umieścić większość mojej logiki aplikacji do pliku w lib, a następnie mieć skrypt w bin który wygląda mniej więcej tak:

#!/usr/bin/env ruby 

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

Kolejną zaletą jest to, że łatwiej zrobić testy jednostkowe czy ładowanie logika aplikacji nie uruchamia się automatycznie.

83

Od rubinu 1.9 można użyć require_relative.

+0

O Boże, żałuję, że nie widziałem twojej odpowiedzi wcześniej. –

Powiązane problemy