web-dev-qa-db-fra.com

Pourquoi le chemin relatif ne fonctionne pas dans Ruby require

Je commence à apprendre Ruby, une chose que je ne comprends pas, pourquoi le chemin relatif pour la directive require ne fonctionne pas dans Ruby. C'est quelque chose qui fonctionne presque dans tous les langages de script que je connais maintenant (JSP, PHP ...). J'explique avec un vrai exemple. J'ai un dossier nommé formes qui contient 3 classes forme, rectangle et carré. J'ai également un autre fichier test_shapes.rb d'où j'appelle et teste mes classes. Lorsque j'importe mes classes dans le fichier principal comme ceci:

require "./shape"
require "./rectangle"
require "./square"

J'ai une erreur pour les fichiers introuvables. Lorsque j'inclus le nom de mon sous-dossier comme ceci:

require "./shapes/shape"
require "./shapes/rectangle"
require "./shapes/square"

Le code fonctionne parfaitement. Parce que j'ai spécifié le chemin complet vers le répertoire racine du projet (le dossier lib je pense). Lorsque j'inclus, j'inclus le chemin absolu vers le disque dur, comme ceci:

require "#{File.dirname(__FILE__)}/shape"
require "#{File.dirname(__FILE__)}/rectangle"
require "#{File.dirname(__FILE__)}/square"

Cela fonctionne également parfaitement.

Donc, je veux juste une explication si je sais pourquoi la première méthode d'importation (le chemin relatif vers le dossier actuel) ne fonctionne pas.

22
Amaynut

Le chemin relatif est basé sur le répertoire de travail. Je suppose qu'il y a un fichier principal dans le même répertoire. Si vous exécutez Ruby ./shapes/main.rb à la racine du projet, Ruby essayez de trouver {project_root}/shape.rb, ne pas {project_root}/shapes/shape.rb. Ça ne marche pas.

Vous devez utiliser require_relative comme ci-dessous.

# {project_root}/shapes/main.rb
require_relative './shape'
require_relative './rectangle'
require_relative './square'
33
nacyot

Vous utilisez un chemin relatif. Et ils sont relatifs à l'endroit où votre script est exécuté. C'est généralement une mauvaise idée. Vous devez utiliser soit le chemin absolu, soit le chemin relatif vers le fichier exact où require est exécuté.

require File.expand_path("../shape", __FILE__)

PS: require_relative semble plus laconique

6
fl00r

require (name) → true ou false Charge le nom donné, renvoyant true en cas de succès et false si la fonctionnalité est déjà chargée.

Si le nom de fichier ne se résout pas en un chemin absolu, il sera recherché dans les répertoires répertoriés dans $ LOAD_PATH ($ :).

Si le nom de fichier a l'extension ".rb", il est chargé en tant que fichier source; si l'extension est ".so", ".o" ou ".dll", ou l'extension de bibliothèque partagée par défaut sur la plate-forme actuelle, Ruby charge la bibliothèque partagée en tant que Ruby extension. Sinon, Ruby essaie d'ajouter ".rb", ".so", et ainsi de suite au nom jusqu'à ce qu'il soit trouvé. Si le fichier nommé est introuvable, une LoadError sera levée.

Pour les extensions Ruby, le nom de fichier donné peut utiliser n'importe quelle extension de bibliothèque partagée. Par exemple, sous Linux, l'extension socket est "socket.so" et nécessite 'socket.dll' chargera l'extension socket.

Le chemin absolu du fichier chargé est ajouté à $ LOADED_FEATURES ($ "). Un fichier ne sera pas chargé à nouveau si son chemin apparaît déjà dans $". Par exemple, exigez "a"; require './a' ne chargera plus a.rb.

require "my-library.rb" require "db-driver" Toutes les constantes ou globales du fichier source chargé seront disponibles dans l'espace de noms global du programme appelant. Cependant, les variables locales ne seront pas propagées à l'environnement de chargement.

require_relative (string) → true or false Ruby essaie de charger la bibliothèque nommée chaîne par rapport au chemin du fichier requis. Si le chemin du fichier ne peut pas être déterminé, une LoadError est levée. Si un fichier est chargé vrai est retourné et faux sinon.

Réf: http://Ruby-doc.org/core-2.1.2/Kernel.html#require-method

1
Vaibhav