2009-04-25 11 views
51

Esiste un modo più breve per richiedere un file che si trova nella stessa directory (come lo script in esecuzione)?C'è un modo più breve per richiedere un file nella stessa directory in ruby?

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

Ho letto che require "my_script" e require "./my_script" sarà effettivamente caricare lo script due volte (ruby non riconosce che in realtà è lo stesso script), e questo è il motivo per cui si consiglia File.expand_path: se viene utilizzato ogni volta che il lo script è richiesto, quindi verrà caricato solo una volta.

Sembra strano per me che un linguaggio conciso come Ruby non sembra avere una soluzione più breve. Ad esempio, Python ha semplicemente questo:

import .some_other_module_in_the_same_directory 

Credo che avrei potuto scimmia-patch require ... ma questo è solo il male! ;-)

risposta

2

Quanto sopra funzionerà anche quando esegui lo script da qualche altra directory. Tuttavia, all'interno della stessa directory, i moduli più brevi a cui si fa riferimento funzionano come previsto e almeno per Ruby 1.9 non daranno luogo a una doppia richiesta.

testa.rb

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

testb.rb

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

esecuzione 'ruby testa.rb' si tradurrà in:

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

Tuttavia, la forma più funziona anche da un'altra directory (ad esempio ruby ​​somedir/script.rb)

2

mettere questo in una directory di libreria standard (da qualche parte che è già nel vostro loadpath predefinito $:):

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

Poi, questo dovrebbe funzionare

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

caller dà accesso al callstack corrente e racconta tu che file e dove, così push-loadpath.rb usa quello per aggiungere il file che è load al percorso di caricamento.

Si noti che è necessario il file load anziché require, in modo che il corpo possa essere richiamato più volte (una volta ogni volta che si desidera modificare il percorso di caricamento).

In alternativa, si potrebbe avvolgere il corpo in un metodo,

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

Questo ti permetterebbe di require, e usarlo in questo modo:

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

richiedono solo filename.

Sì, lo importerà due volte se lo specifichi come filename e ./filename, quindi non farlo. Non stai specificando lo .rb, quindi non specificare il percorso.Io di solito mettere la maggior parte della mia logica dell'applicazione in un file in lib, e quindi avere uno script in bin che sembra qualcosa di simile:

#!/usr/bin/env ruby 

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

Un altro vantaggio è che trovo più facile fare test di unità, se il carico la logica dell'applicazione non avvia automaticamente l'esecuzione.

83

Da ruby ​​1.9 è possibile utilizzare require_relative.

+0

Oh dio, vorrei aver visto la tua risposta prima. –

Problemi correlati