web-dev-qa-db-fra.com

Existe-t-il un moyen plus court d'exiger un fichier dans le même répertoire dans ruby?

Existe-t-il un moyen plus court d'exiger un fichier situé dans le même répertoire (que le script en cours d'exécution)?

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

Je lis ça require "my_script" et require "./my_script" chargera réellement le script deux fois (Ruby ne reconnaîtra pas qu'il s'agit en fait du même script), et c'est la raison pour laquelle File.expand_path est recommandé: s'il est utilisé à chaque fois que le script est requis, il ne sera chargé qu'une seule fois.

Il me semble étrange qu'un langage concis comme Ruby ne semble pas avoir de solution plus courte. Par exemple, python a simplement ceci:

import .some_other_module_in_the_same_directory

Je suppose que je pourrais patch monkey require... mais c'est juste mal! ;-)

56
MiniQuark

Depuis Ruby 1.9 vous pouvez utiliser require_relative.

92
knut

Il suffit de filename.

Oui, il l'importera deux fois si vous le spécifiez comme filename et ./filename, alors ne fais pas ça. Vous ne spécifiez pas le .rb, donc ne spécifiez pas le chemin. Je place généralement la majeure partie de ma logique d'application dans un fichier dans lib, puis j'ai un script dans bin qui ressemble à ceci:

#!/usr/bin/env Ruby

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

Un autre avantage est que je trouve plus facile de faire des tests unitaires si le chargement de la logique d'application ne démarre pas automatiquement son exécution.

12
dvorak

Ce qui précède fonctionnera même lorsque vous exécutez le script à partir d'un autre répertoire. Cependant, à l'intérieur du même répertoire, les formulaires plus courts auxquels vous faites référence fonctionnent comme prévu et au moins pour Ruby 1.9 n'entraînera pas de double besoin.

testa.rb

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

testb.rb

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

exécuter 'Ruby testa.rb' entraînera:

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

Cependant, le formulaire plus long fonctionnera même à partir d'un autre répertoire (par exemple. Ruby somedir/script.rb)

3
woods

Placez-le dans un répertoire de bibliothèque standard (quelque part qui se trouve déjà dans votre chemin de chargement par défaut $:):

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

Ensuite, cela devrait fonctionner

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

caller vous donne accès à la pile d'appels actuelle et vous indique quel fichier et où, donc Push-loadpath.rb l'utilise pour ajouter le fichier qui load 'l'a ajouté au chemin de chargement.

Notez que vous devez load le fichier, plutôt que require, afin que le corps puisse être appelé plusieurs fois (une fois pour chaque fois que vous souhaitez modifier le chemin de chargement).

Alternativement, vous pouvez envelopper le corps dans une méthode,

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

Cela vous permettrait de require, et de l'utiliser de cette façon:

% ls /path/to/
bin.rb lib1.rb lib2.rb #...
% cat /path/to/bin.rb
require 'Push-loadpath'
Push_loadpath
require 'lib1'
require 'lib2'
#...
3
rampion