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

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

Regardez les documents :

require_relative complète la méthode requirejse 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 pour celles-ci dans le répertoire “test / data” du test, vous pouvez utiliser une ligne comme celle-ci dans un scénario de test:

 require_relative "data/customer_data_1" 

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 si il soulève une __FILE__ .

Cela implique que:

  • require_relative 'a' et require_relative './a' exigent par rapport au fichier en cours ( __FILE__ ).

    C’est ce que vous voulez utiliser lorsque vous avez besoin dans votre bibliothèque, car vous ne voulez pas que le résultat dépende du répertoire en cours de l’appelant.

  • eval('require_relative("a.rb")') déclenche __FILE__ car __FILE__ n’est pas défini dans eval .

    C’est pourquoi vous ne pouvez pas utiliser require_relative dans les tests RSpec, qui sont eval .

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

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

  • require 'a.rb' utilise le chemin de recherche ( $LOAD_PATH ) à demander. Il ne trouve pas les fichiers relatifs au répertoire ou au chemin en cours.

    Ceci n’est pas possible avec require_relative car 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 utiliser require car il est plus court et plus efficace:

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

Lire la source

Lorsque les documents ne sont pas clairs, je vous recommande de consulter les sources (bascule de 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__ 

De l’API Ruby :

require_relative complète la méthode requirejse en vous permettant de charger un fichier relatif au fichier contenant l’instruction require_relative.

Lorsque vous utilisez pour charger un fichier, vous accédez généralement à une fonctionnalité correctement installée et rendue accessible 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” dans un projet, non destinés à une utilisation externe.

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 / data” du test, 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 de la bibliothèque de Ruby (et pour une bonne raison), une demande 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.

chemin doit répondre à to_str.

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

require utilise le répertoire courant à partir duquel vous exécutez le programme

require_relative utilise le répertoire de l’emplacement de ce programme lui-même

Par exemple, si un programme est dans ~/code et s’appelle 1.rb et que vous avez fait un cd dans ce répertoire

 cd ~/code 

et vous essayez de lancer le programme ruby ​​avec

 ruby 1.rb 

puis dans 1.rb

 require './2.rb' require_relative '3.rb' 

les deux vont travailler.

Cependant, si vous êtes dans un autre répertoire, dites

 cd ~/tmp 

et vous essayez d’exécuter le programme avec

 ruby ../1.rb 

alors vous aurez une erreur telle que

 /home/durrantm/.rvm/rubies/ruby-2.1.2/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:54:in `require': cannot load such file -- ./2.rb (LoadError) from /home/durrantm/.rvm/rubies/ruby-2.1.2/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:54:in `require' from ../1.rb:1:in `
'

en essayant d’utiliser

 require './2.rb' 

alors qu’utiliser

 require_relative '3.rb' 

fonctionne toujours correctement _car la référence (à 3.rb ) est relative au répertoire dans lequel se trouve le programme ( 1.rb ).

Les meilleures réponses sont correctes mais profondément techniques. Pour les plus récents au Ruby–

  • require_relative sera très probablement utilisé pour importer du code d’un autre fichier que vous avez écrit.

Par exemple, 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 appendiez des require_relative 'data' .

il est important de noter que ces fichiers ne doivent pas nécessairement se trouver dans le même répertoire. require_relative '../../folder1/folder2/data' est également valide.

  • require sera très probablement utilisé pour importer du code d’une bibliothèque que quelqu’un d’autre a écrit.

Par exemple, que faire si vous souhaitez utiliser l’une des fonctions d’aide fournies dans la bibliothèque active_support ? Vous devrez installer la gem 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.

Je viens de voir le code de RSpec a quelques commentaires sur require_relative étant O (1) constant et require être O (N) linéaire. Donc, la différence réside probablement dans le fait que require_relative est l’ require_relative préférée.

Je veux append 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 qu’il doit être exécuté avec un chemin UNC \ nom_serveur \ nom_partage \ require_relative './1.rb' Je ne me mêle pas de la discussion pour d’autres raisons.