web-dev-qa-db-fra.com

Quelle est la difference entre require_relative et require in Ruby?

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

293
agentbanks217

Il suffit de regarder le docs :

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.

Par exemple, si vous avez des classes de tests unitaires dans le répertoire "test" et des données les concernant 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"
291
miku

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 sinon LoadError est généré.

Ceci implique que:

  • _require_relative 'a'_ et _require_relative './a'_ require par rapport à fichier actuel (___FILE___).

    C’est ce que vous voulez utiliser lorsque vous en avez besoin dans 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")') soulève LoadError car ___FILE___ n'est pas défini dans eval.

    C'est pourquoi vous ne pouvez pas utiliser _require_relative_ dans les tests RSpec, qui obtiennent evaled.

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

  • _require './a.rb'_ requiert par rapport à répertoire actuel

  • _require 'a.rb'_ utilise le chemin de recherche (_$LOAD_PATH_) à exiger. Il ne trouve pas les fichiers relatifs au répertoire ou chemin actuel.

    Ceci n’est pas possible avec _require_relative_ car la documentation dit que la recherche de chemin ne se produit que lorsque "le nom du fichier ne se résout pas en chemin absolu" (c’est-à-dire qu'il 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 utiliser require car elle est plus courte et plus efficace:

  • _require '/a.rb'_ et _require_relative '/a.rb'_ requièrent tous deux le chemin absolu.

Lecture du source

Lorsque les documents ne sont pas clairs, je vous recommande de jeter un coup d'œil aux sources (bascule source dans les documents). Dans certains cas, il est utile de 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__)))
_

parce que:

_rb_file_absolute_path   =~ File.expand_path
rb_file_dirname1        =~ File.dirname
rb_current_realfilepath =~ __FILE__
_

De Ruby API :

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 à une fonctionnalité correctement installée et rendue accessible sur votre système. require n’offre pas une bonne solution pour charger des fichiers dans le code du projet. Cela peut être utile lors d'une phase de développement, pour accéder aux données de test ou même pour accéder à des fichiers "bloqués" dans un projet, non destiné à être utilisé à l'extérieur.

Par exemple, si vous avez des classes de tests unitaires dans le répertoire "test" et des données les concernant 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" 

Etant donné que ni "test" ni "test/données" ne sont vraisemblablement dans le chemin de la bibliothèque de Ruby (et pour de bonnes raisons), une exigence normale ne les trouvera pas. require_relative est une bonne solution à ce problème particulier.

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

chemin doit répondre à to_str.

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

74
svilenv

Sommaire

Utilisez require pour les gemmes installées

Utilisez _require_relative_ pour les fichiers locaux

require utilise votre $LOAD_PATH pour rechercher les fichiers.
_require_relative_ utilise l'emplacement actuel du fichier à l'aide de l'instruction


exiger

Require suppose que vous ayez installé (par exemple _gem install [package]_) un package quelque part sur votre système pour cette fonctionnalité.

Lorsque vous utilisez require, vous pouvez utiliser le format "_./_" pour un fichier du répertoire actuel, par exemple. _require "./my_file"_ mais ce n'est pas une pratique courante ou recommandée et vous devriez utiliser _require_relative_ à la place.

require_relative

Cela signifie simplement inclure le fichier "par rapport à l'emplacement du fichier avec l'instruction require_relative". Je recommande généralement que les fichiers se trouvent "dans" l'arborescence de répertoires actuelle, par opposition à "en haut", par exemple. ne pas utiliser

_require_relative '../../../filename'
_

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

Notez que _require_relative_ utilise le répertoire en cours du fichier avec l'instruction require_relative (le répertoire actuel dans lequel vous utilisez la commande n'est donc pas nécessairement obligatoire). ). Ceci garde le chemin _require_relative_ "stable", car il est toujours relatif au fichier le nécessitant de la même manière.

44
Michael Durrant

Les premières réponses sont correctes, mais profondément techniques. Pour ceux plus récents au Ruby--

  • require_relative sera probablement utilisé pour importer le code d'un autre fichier que vous avez écrit.

par exemple, que se passe-t-il si vous avez des données dans ~/my-project/data.rb et que vous souhaitez les inclure dans ~/my-project/solution.rb? dans solution.rb vous 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 le code d'une bibliothèque écrite par quelqu'un d'autre.

par exemple, si vous souhaitez utiliser l'une des fonctions d'assistance fournies dans la bibliothèque active_support? vous devez installer la gemme avec gem install activesupport puis dans le fichier require 'active_support'.

require 'active_support/all'
"FooBar".underscore

Dit différemment--

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

  • require nécessite un fichier inclus dans $ LOAD_PATH.

23
common-nighthawk

Je viens de voir que le code de RSpec contient des commentaires sur require_relative étant O(1) constante et require étant O(N) linéaire. Donc, probablement la différence est que require_relative est le préféré par rapport à require.

14
mech

Je souhaite ajouter que, lorsque vous utilisez Windows, vous pouvez utiliser require './1.rb' si le script est exécuté en local ou à partir d'un lecteur réseau mappé, mais lorsqu'il est exécuté à partir d'un chemin UNC\nom_serveur\nom_du_nom \, vous devez utiliser require_relative './1.rb'. Je ne me mêle pas à la discussion pour l'utiliser pour d'autres raisons.

1
peter