web-dev-qa-db-fra.com

Pourquoi Ruby 1.9.2 supprime-t-il "." De LOAD_PATH, et quelle est l’alternative?

Les dernières modifications apportées à Ruby 1.9.2 ne rend plus le répertoire actuel . une partie de votre LOAD_PATH. J'ai un nombre non négligeable de fichiers Rakefiles qui supposent que . fait partie du LOAD_PATH, donc cela les a cassés (ils ont signalé "aucun fichier à charger" pour toutes les instructions require basées sur le chemin du projet). Y avait-il une justification particulière à cela?

Comme pour un correctif, ajouter $: << "." partout fonctionne, mais semble incroyablement hacky et je ne veux pas faire ça. Quel est le moyen préféré pour rendre mon Rakefiles 1.9.2+ compatible?

154
John Feminella

C'était considéré comme un risque "de sécurité".

Vous pouvez le contourner en utilisant des chemins absolus

File.expand_path(__FILE__) et al

ou faire

require './filename' (ironically).

ou en utilisant

require_relative 'filename'

ou ajouter un répertoire "include"

Ruby -I . ...

ou la même chose, en utilisant irb;

$irb -I .
140
rogerdpack

Il y a deux raisons:

  • robustesse et
  • sécurité

Les deux sont basés sur le même principe sous-jacent: en général, vous ne pouvez simplement pas savoir quel est le répertoire actuel, lorsque votre code est exécuté. Ce qui signifie que, lorsque vous avez besoin d'un fichier et que vous dépendez de son emplacement dans le répertoire en cours, vous ne pouvez pas contrôler si ce fichier sera même là ou s'il s'agit du fichier que vous espérez réellement y être.

34
Jörg W Mittag

Comme d'autres personnes le soulignent, c'est un risque pour la sécurité parce que . dans votre chemin de chargement fait référence au répertoire de travail actuel Dir.pwd, pas le répertoire du fichier en cours de chargement. Ainsi, quiconque exécute votre script peut changer cela simplement en cding dans un autre répertoire. Pas bon!

J'ai utilisé des chemins complets construits à partir de __FILE__ comme alternative.

require File.expand_path(File.join(File.dirname(__FILE__), 'filename'))

Contrairement à require_relative, ceci est rétrocompatible avec Ruby 1.8.7.

16
Jonathan Tran

Utilisation require_relative 'file_to_require'

Ajoutez ceci dans votre code pour faire un travail require_relative en 1.8.7:

unless Kernel.respond_to?(:require_relative)
  module Kernel
    def require_relative(path)
      require File.join(File.dirname(caller.first), path.to_str)
    end
  end
end
8
Tyler Brock

'.' sur votre chemin a longtemps été considéré comme une mauvaise chose dans le monde Unix (voir, par exemple, http://www.faqs.org/faqs/unix-faq/faq/part2/section-13.html ). Je suppose que les Ruby) ont été persuadés de la sagesse de ne pas le faire.

6
Rodger

J'ai trouvé que c'était un changement déroutant jusqu'à ce que je réalise quelques choses.

Vous pouvez définir RUBYLIB dans votre .profile (Unix) et continuer à vivre comme avant:

export RUBYLIB="."

Mais comme mentionné ci-dessus, il a longtemps été considéré comme dangereux de le faire.

Dans la grande majorité des cas, vous pouvez éviter les problèmes en appelant simplement vos scripts Ruby) avec un préfixe '.', Par exemple ./scripts/server.

3
Dylan

Comme Jörg W Mittag l'a fait remarquer, je pense que ce que vous voulez utiliser, c'est require_relative donc le fichier dont vous avez besoin est relatif au fichier source de la déclaration require et non au répertoire de travail en cours.

Vos dépendances doivent être relatives à votre fichier de construction rake.

3
Martin