57 votes

Existe-t-il un moyen plus court de demander un fichier dans le même répertoire en ruby ?

Existe-t-il un moyen plus court pour 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')

J'ai lu que require "my_script" y require "./my_script" va en fait charger 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, alors il ne sera chargé qu'une seule fois.

Il me semble bizarre 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 faire du "monkey-patch require ... mais c'est juste le mal ! ;-)

102voto

knut Points 10107

Depuis ruby 1.9, vous pouvez utiliser require_relative .

Vérifiez le dernier document para require_relative o une autre version de l'API de base.

0 votes

Oh mon dieu, j'aurais aimé voir ta réponse plus tôt.

13voto

dvorak Points 9516

Il suffit de demander filename .

Oui, il l'importera deux fois si vous le spécifiez en tant que filename y ./filename alors ne le faites pas. 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 le répertoire lib et ensuite avoir un script en bin qui ressemble à quelque chose comme ça :

#!/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 d'effectuer des tests unitaires si le chargement de la logique de l'application ne déclenche pas automatiquement son exécution.

3voto

Ce qui précède fonctionnera même si vous exécutez le script depuis un autre répertoire. Cependant, à l'intérieur du même répertoire, les formes courtes auxquelles vous faites référence fonctionnent comme prévu et, au moins pour ruby 1.9, n'entraîneront pas de double-requête.

testa.rb

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

testb.rb

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

L'exécution de 'ruby testa.rb' donnera le résultat suivant :

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

Cependant, la forme longue fonctionnera même à partir d'un autre répertoire (par exemple ruby somedir/script.rb)

3voto

rampion Points 38697

Placez ceci dans un répertoire de bibliothèque standard (quelque part qui est déjà dans votre chemin de chargement par défaut). $: ):

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

Alors, 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 courante, et vous indique quel fichier et où, donc push-loadpath.rb l'utilise pour ajouter le fichier que load sur le chemin de chargement.

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

Alternativement, vous pourriez 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 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'
#...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X