97 votes

Ajout d'un répertoire à $LOAD_PATH (Ruby)

J'ai vu deux techniques couramment utilisées pour ajouter le répertoire du fichier en cours d'exécution au $LOAD_PATH (ou $ :). Je vois les avantages de faire cela dans le cas où vous ne travaillez pas avec une gemme. L'une semble plus verbeuse que l'autre, évidemment, mais y a-t-il une raison de choisir l'une plutôt que l'autre ?

La première méthode, verbeuse (pourrait être excessive) :

$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__)))

et le plus direct, le plus rapide et le plus sale :

$:.unshift File.dirname(__FILE__)

Y a-t-il une raison de choisir l'un plutôt que l'autre ?

2 votes

A légèrement version moins verbeuse de la version verbeuse : File.expand_path(File.dirname(__FILE__)).tap {|pwd| $LOAD_PATH.unshift(pwd) unless $LOAD_PATH.include?(pwd)}

0 votes

Qu'en est-il de la clause "à moins que" ? Comment les deux clauses ci-dessus peuvent-elles être équivalentes ?

0 votes

En tant que personne venue ici pour essayer de comprendre comment l'utiliser, c'est super cryptique. Je ne vois pas d'où vient le nom du répertoire dans les exemples. J'apprécierais que quelqu'un puisse clarifier cela.

155voto

Le chemin de chargement de Ruby est très souvent écrit comme $ : mais ce n'est pas parce qu'il est court qu'il est meilleur. Si vous préférez la clarté à l'intelligence, ou si la brièveté pour elle-même vous démange, vous n'avez pas besoin de le faire juste parce que tout le monde le fait. Dites bonjour à ...

$LOAD_PATH

... et dire au revoir à ...

# I don't quite understand what this is doing...
$:

54voto

Ryan Bigg Points 64561

Je dirais que c'est $:.unshift File.dirname(__FILE__) sur l'autre, simplement parce que j'en ai vu beaucoup plus d'utilisation dans le code que la $LOAD_PATH un, et il est plus court aussi !

0 votes

Lorsque j'ai commencé à utiliser Ruby, je pensais évidemment que $LOAD_PATH était mieux. Mais une fois que vous avez dépassé le statut de débutant, je n'utiliserais $LOAD_PATH que si j'essayais de rendre mon code plus lisible pour un débutant. C'est un compromis. Cela dépend de la façon dont le code est "public", tant que l'utilisation de la mémoire est la même pour chacun, ce qui, je suppose, est essentiellement le cas.

9 votes

Cela dépend du guide de style que vous suivez pour votre projet. Les guides populaires Guide de style Ruby dit : "Évitez d'utiliser les variables spéciales de style Perl (comme $ :, $ ;, etc.). Elles sont assez cryptiques et leur utilisation dans tout sauf dans des scripts à une ligne est déconseillée."

25voto

Luke Antins Points 1317

Je n'aime pas trop la méthode "vite fait bien fait". Quiconque découvre Ruby se demandera ce qu'il faut faire $:. est.

Je trouve cela plus évident.

libdir = File.dirname(__FILE__)
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)

Ou si je tiens à avoir le chemin complet...

libdir = File.expand_path(File.dirname(__FILE__))
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)

UPDATE 2009/09/10

Ces derniers temps, j'ai fait ce qui suit :

$:.unshift(File.expand_path(File.dirname(__FILE__))) unless
    $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))

Je l'ai vu dans tout un tas de projets ruby différents en parcourant GitHub.

Il semble que ce soit la convention ?

0 votes

@LukeAntins, c'est vraiment génial mais où dois-je "amorcer" load_path dans l'application ?

0 votes

@gaussblurinc Quelque part "près du sommet" de votre lib/application, mais cela dépend vraiment. Si vous avez un bin qui était toujours relatif à votre code et il n'a jamais été géré que par le bin ... bootstrap dans la corbeille. Si vous avez une bibliothèque, alors bootstrap au début du code de votre bibliothèque comme dans lib/code.rb pour avoir accès à tout ce qui se trouve sous lib/code/ . J'espère que ces propos vous aideront !

1 votes

RuboCop m'informe que __dir__ peut être utilisé pour obtenir un chemin vers le répertoire du fichier courant.

8voto

Dave Robertson Points 175

La meilleure solution que j'ai trouvée pour ajouter un répertoire via un chemin relatif lorsque l'on utilise Rspec. Je trouve que c'est assez verbeux, mais que c'est aussi un bon moyen d'expression.

$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))

8voto

Dyba Points 88

Si vous tapez script/console dans votre projet Rails et entrez $: vous obtiendrez un tableau contenant tous les répertoires nécessaires au chargement de Ruby. L'enseignement de ce petit exercice est que $: est un tableau. Cela étant, vous pouvez exécuter des fonctions sur ce tableau, par exemple en faisant précéder d'autres répertoires de la balise unshift ou la méthode << opérateur. Comme vous l'avez laissé entendre dans votre déclaration $: et $LOAD_PATH sont les mêmes.

L'inconvénient de la méthode rapide et sale que vous avez mentionnée est le suivant : si vous avez déjà le répertoire dans votre chemin de démarrage, il se répétera.

Exemple :

J'ai créé un plugin appelé todo. Mon répertoire est structuré comme suit :

/---vendor
  |
  |---/plugins
        |
        |---/todo
              |
              |---/lib
                    |
                    |---/app
                          |
                          |---/models
                          |---/controllers
              |
              |---/rails
                    |
                    |---init.rb

Dans le fichier init.rb, j'ai entré le code suivant :

## In vendor/plugins/todo/rails/init.rb
    %w{ models controllers models }.each do |dir|
      path = File.expand_path(File.join(File.dirname(__FILE__), '../lib', 'app', dir))
      $LOAD_PATH << path
      ActiveSupport::Dependencies.load_paths << path
      ActiveSupport::Dependencies.load_once_paths.delete(path)
    end 

Remarquez comment je demande au bloc de code d'exécuter les actions à l'intérieur du bloc sur les chaînes "models", "controllers" et "models", où je répète "models". (FYI, %w{ ... } est juste une autre façon de dire à Ruby de contenir un tableau de chaînes de caractères). Lorsque je lance script/console je tape ce qui suit :

>> puts $:

Et je tape cela pour qu'il soit plus facile de lire le contenu de la chaîne. La sortie que j'obtiens est :

...
...
./Users/Me/mySites/myRailsApp/vendor/plugins/todo/lib/app/models
./Users/Me/mySites/myRailsApp/vendor/plugins/todo/lib/app/controllers
./Users/Me/mySites/myRailsApp/vendor/plugins/todo/lib/app/models

Comme vous pouvez le constater, bien qu'il s'agisse d'un exemple aussi simple que celui que j'ai pu créer en utilisant un projet sur lequel je travaille actuellement, si vous ne faites pas attention, la méthode rapide et sale mènera à des chemins répétés. La méthode plus longue vérifie les chemins répétés et s'assure qu'ils ne se produisent pas.

Si vous êtes un programmeur Rails expérimenté, vous avez probablement une très bonne idée de ce que vous faites et ne commettez probablement pas l'erreur de répéter des chemins. Si vous êtes un débutant, j'opterais pour le chemin le plus long jusqu'à ce que vous compreniez vraiment ce que vous faites.

0 votes

Votre réponse est très utile et également bien expliquée. Modification suggérée : la méthode load_paths et load_once_paths.delete ont été dépréciés. Il serait utile de mettre à jour les lignes qui y font référence comme suit : ActiveSupport::Dependencies.autoload_paths << path ActiveSupport::Dependencies.autoload_once_paths.delete(path)

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