Quelle est la différence entre require_relative et require en Ruby?

302

Quelle est la différence entre require_relativeet requireen Ruby?

agentbanks217
la source
9
Avant 1.9.2, il n'était pas nécessaire de require_relative, car le répertoire actuel du script était dans $:. Voir stackoverflow.com/questions/2900370
Nakilon
1
require_relative nécessite un fichier spécifiquement pointé par rapport au fichier qui l'appelle. require requiert un fichier inclus dans $ LOAD_PATH.
Donato
article utile sur les différences => medium.com/@ellishim/…
ahmed hamdy

Réponses:

298

Regardez les documents :

require_relativecomplète la méthode intégrée requireen vous permettant de charger un fichier relatif au fichier contenant l' require_relativeinstruction.

Par exemple, si vous avez des classes de tests unitaires dans le répertoire "test" et des données pour celles-ci dans le répertoire test "test / data", vous pouvez utiliser une ligne comme celle-ci dans un scénario de test:

require_relative "data/customer_data_1"
miku
la source
28
Y a-t-il une différence entre require './file.rb'et require_relative 'file.rb'?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
69
@CiroSantilli Oui. require_relativevous permet de "charger un fichier relatif au fichier contenant l' require_relativeinstruction ". Avec require, ./indique un chemin relatif à votre répertoire de travail actuel.
Ajedi32
17
Je pense qu'il est plus important de noter que la require strrecherche se fera toujours dans les répertoires de $ LOAD_PATH. Vous devez utiliser require_relativelorsque le fichier que vous devez charger existe quelque part par rapport au fichier qui appelle le chargement. Réserve requirepour les dépendances "externes".
rthbound
97

require_relative est un sous-ensemble pratique de require

require_relative('path')

équivaut à:

require(File.expand_path('path', File.dirname(__FILE__)))

si __FILE__est défini, ou il soulèveLoadError contraire.

Ceci implique que:

  • require_relative 'a'et require_relative './a'exiger par rapport au fichier actuel ( __FILE__).

    C'est ce que vous voulez utiliser lorsque vous avez besoin de l'intérieur de votre bibliothèque, car vous ne voulez pas que le résultat dépende du répertoire actuel de l'appelant.

  • eval('require_relative("a.rb")')lève LoadErrorcar __FILE__n'est pas défini à l'intérieur eval.

    C'est pourquoi vous ne pouvez pas utiliser require_relativedans les tests RSpec, qui sont evalédités.

Les opérations suivantes ne sont possibles qu'avec require:

  • require './a.rb'requiert par rapport au répertoire courant

  • require 'a.rb'utilise le chemin de recherche ( $LOAD_PATH) pour exiger. Il ne trouve pas les fichiers relatifs au répertoire ou au chemin actuel.

    Ce n'est pas possible avec require_relativecar les documents disent que la recherche de chemin ne se produit que lorsque "le nom de fichier ne se résout pas en un chemin absolu" (c'est-à-dire commence par /ou ./ou ../), ce qui est toujours le cas pour File.expand_path.

L'opération suivante est possible avec les deux, mais vous voudrez l'utiliser requirecar elle est plus courte et plus efficace:

  • require '/a.rb'et les require_relative '/a.rb'deux nécessitent le chemin absolu.

Lire la source

Lorsque les documents ne sont pas clairs, je vous recommande de jeter un œil aux sources (basculer la source dans les documents). Dans certains cas, cela aide à comprendre ce qui se passe.

exiger:

VALUE rb_f_require(VALUE obj, VALUE fname) {
  return rb_require_safe(fname, rb_safe_level());
}

require_relative:

VALUE rb_f_require_relative(VALUE obj, VALUE fname) {
    VALUE base = rb_current_realfilepath();
    if (NIL_P(base)) {
        rb_loaderror("cannot infer basepath");
    }
    base = rb_file_dirname(base);
    return rb_require_safe(rb_file_absolute_path(fname, base), rb_safe_level());
}

Cela nous permet de conclure que

require_relative('path')

est le même que:

require(File.expand_path('path', File.dirname(__FILE__)))

car:

rb_file_absolute_path   =~ File.expand_path
rb_file_dirname1        =~ File.dirname
rb_current_realfilepath =~ __FILE__
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
la source
74

Depuis l'API Ruby :

require_relative complète la méthode intégrée require en vous permettant de charger un fichier relatif au fichier contenant l'instruction require_relative.

Lorsque vous utilisez require pour charger un fichier, vous accédez généralement à des fonctionnalités qui ont été correctement installées et rendues accessibles dans votre système. require n'offre pas une bonne solution pour charger des fichiers dans le code du projet. Cela peut être utile pendant une phase de développement, pour accéder à des données de test, ou même pour accéder à des fichiers qui sont "verrouillés" à l'intérieur d'un projet, non destinés à un usage extérieur.

Par exemple, si vous avez des classes de tests unitaires dans le répertoire "test" et des données pour celles-ci dans le répertoire test "test / data", vous pouvez utiliser une ligne comme celle-ci dans un scénario de test:

require_relative "data/customer_data_1" 

Comme ni "test" ni "test / data" ne sont susceptibles d'être dans le chemin d'accès à la bibliothèque de Ruby (et pour une bonne raison), une exigence normale ne les trouvera pas. require_relative est une bonne solution pour ce problème particulier.

Vous pouvez inclure ou omettre l'extension (.rb ou .so) du fichier que vous chargez.

le chemin doit répondre à to_str.

Vous pouvez trouver la documentation sur http://extensions.rubyforge.org/rdoc/classes/Kernel.html

svilenv
la source
50

Résumé

Utiliser requirepour les gemmes installées

Utiliser require_relativepour les fichiers locaux

requireutilise votre $LOAD_PATHpour rechercher les fichiers.
require_relativeutilise l'emplacement actuel du fichier à l'aide de l'instruction


exiger

Exiger repose sur le fait que vous avez installé (par exemple gem install [package]) un package quelque part sur votre système pour cette fonctionnalité.

Lors de l'utilisation, requirevous pouvez utiliser le ./format " " pour un fichier dans le répertoire courant, par exemple, require "./my_file"mais ce n'est pas une pratique courante ou recommandée et vous devez utiliser à la require_relativeplace.

require_relative

Cela signifie simplement inclure le fichier «par rapport à l'emplacement du fichier avec l'instruction require_relative». Je généralement recommande que les fichiers doivent être « dans » l'arborescence du répertoire courant par opposition à « haut », par exemple , ne le font pas usage

require_relative '../../../filename'

(jusqu'à 3 niveaux de répertoire) dans le système de fichiers car cela a tendance à créer des dépendances inutiles et fragiles. Cependant, dans certains cas, si vous êtes déjà «profond» dans une arborescence de répertoires, une «branche d'arborescence de répertoires» peut être nécessaire. Plus simplement peut-être, n'utilisez pas require_relative pour les fichiers en dehors de ce référentiel (en supposant que vous utilisez git qui est en grande partie une norme de facto à ce stade, fin 2018).

Notez que require_relativeutilise le répertoire actuel du fichier avec l' instruction require_relative (donc pas nécessairement votre répertoire actuel à partir duquel vous utilisez la commande). Cela maintient le require_relativechemin "stable" car il est toujours relatif au fichier le nécessitant de la même manière.

Michael Durrant
la source
27

Les meilleures réponses sont correctes, mais profondément techniques. Pour les nouveaux venus chez Ruby:

  • require_relative sera très probablement utilisé pour introduire du code à partir d'un autre fichier que vous avez écrit.

par exemple, que faire si vous avez des données ~/my-project/data.rbet que vous souhaitez les inclure ~/my-project/solution.rb? en solution.rbvous ajouteriez require_relative 'data'.

il est important de noter que ces fichiers n'ont pas besoin d'être dans le même répertoire. require_relative '../../folder1/folder2/data'est également valide.

  • require sera très probablement utilisé pour importer du code à partir d'une bibliothèque écrite par quelqu'un d'autre.

par exemple, que faire si vous souhaitez utiliser l'une des fonctions d'assistance fournies dans la active_supportbibliothèque? vous devrez installer la gemme avec gem install activesupportpuis dans le fichier require 'active_support'.

require 'active_support/all'
"FooBar".underscore

Dit différemment ...

  • require_relative nécessite un fichier spécifiquement pointé par rapport au fichier qui l'appelle.

  • requirenécessite un fichier inclus dans le $LOAD_PATH.

Engoulevent d'Amérique
la source
3
Comment puis-je voter pour cette réponse et l'amener au sommet, afin que chaque visiteur de cette page de questions obtienne une réponse claire et compréhensible immédiatement sans se casser la cervelle?
TiredOfProgramming
16

Je viens de voir que le code de RSpec a un commentaire sur la require_relativeconstante O (1) et la requirelinéarité O (N). Donc, la différence est probablement celle qui require_relativeest préférée require.

mech
la source
1
Intéressant. J'ai atterri ici à la recherche d'informations sur une comparaison de vitesse. Ma pensée était que require_relativec'était plus rapide car le chargeur n'a pas à parcourir le chemin de chargement à la recherche du fichier. Essentiellement, require_relativefournit un lien direct.
Clint Pachl
Première discussion sur la vitesse require_relative et le changelog RSpec .
Clint Pachl
1

Je veux ajouter que lorsque vous utilisez Windows, vous pouvez utiliser require './1.rb'si le script est exécuté localement ou à partir d'un lecteur réseau mappé mais lorsqu'il est exécuté à partir d'un \\servername\sharename\folderchemin UNC que vous devez utiliser require_relative './1.rb'.

Je ne me mêle pas dans la discussion à utiliser pour d'autres raisons.

peter
la source
Je voulais savoir comment charger le require_relativefichier Pourriez-vous s'il vous plaît jeter une idée sur ce stackoverflow.com/questions/43487784/…
Emjey