¿Cuál es la diferencia entre require_relative y require en Ruby?

¿Cuál es la diferencia entre require_relative y require en Ruby?

Solo mira los documentos :

require_relative complementa el método incorporado require al permitirle cargar un archivo que es relativo al archivo que contiene la instrucción require_relative .

Por ejemplo, si tiene clases de prueba unitarias en el directorio “prueba” y datos para ellas bajo el directorio de prueba “prueba / datos”, entonces puede usar una línea como esta en un caso de prueba:

 require_relative "data/customer_data_1" 

require_relative es un subconjunto conveniente de require

 require_relative('path') 

es igual a:

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

si __FILE__ está definido, o sube LoadError caso contrario.

Esto implica que:

  • require_relative 'a' y require_relative './a' requieren relativa al archivo actual ( __FILE__ ).

    Esto es lo que desea usar cuando lo necesite dentro de su biblioteca, ya que no desea que el resultado dependa del directorio actual de la persona que llama.

  • eval('require_relative("a.rb")') LoadError porque __FILE__ no está definido dentro de eval .

    Es por eso que no puede usar require_relative en las pruebas de RSpec, que se eval .

Las siguientes operaciones solo son posibles con require :

  • require './a.rb' requiere relativo al directorio actual

  • require 'a.rb' utiliza la ruta de búsqueda ( $LOAD_PATH ) para requerir. No encuentra archivos relativos al directorio o ruta actual.

    Esto no es posible con require_relative porque los documentos dicen que la búsqueda de ruta solo ocurre cuando “el nombre de archivo no se resuelve en una ruta absoluta” (es decir, comienza con / o ./ o ../ ), que es siempre el caso para File.expand_path .

La siguiente operación es posible con ambos, pero querrá usar require ya que es más corta y más eficiente:

  • require '/a.rb' y require_relative '/a.rb' ambos requieren la ruta absoluta.

Leyendo la fuente

Cuando los documentos no están claros, le recomiendo que eche un vistazo a las fonts (alternar fuente en los documentos). En algunos casos, ayuda a comprender lo que está sucediendo.

exigir:

 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()); } 

Esto nos permite concluir que

 require_relative('path') 

es lo mismo que:

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

porque:

 rb_file_absolute_path =~ File.expand_path rb_file_dirname1 =~ File.dirname rb_current_realfilepath =~ __FILE__ 

De Ruby API :

require_relative complementa el método incorporado require al permitirle cargar un archivo que es relativo al archivo que contiene la instrucción require_relative.

Cuando utiliza require para cargar un archivo, generalmente accede a la funcionalidad que se ha instalado correctamente y se ha hecho accesible en su sistema. require no ofrece una buena solución para cargar archivos dentro del código del proyecto. Esto puede ser útil durante una fase de desarrollo, para acceder a datos de prueba, o incluso para acceder a archivos que están “bloqueados” dentro de un proyecto, no destinados para uso externo.

Por ejemplo, si tiene clases de prueba unitarias en el directorio “prueba” y datos para ellas bajo el directorio de prueba “prueba / datos”, entonces puede usar una línea como esta en un caso de prueba:

 require_relative "data/customer_data_1" 

Dado que es probable que ni “prueba” ni “prueba / datos” estén en la ruta de la biblioteca de Ruby (y por una buena razón), un requisito normal no los encontrará. require_relative es una buena solución para este problema en particular.

Puede incluir u omitir la extensión (.rb o .so) del archivo que está cargando.

la ruta debe responder a to_str.

Puede encontrar la documentación en http://extensions.rubyforge.org/rdoc/classes/Kernel.html

require utiliza el directorio actual desde el que ejecuta el progtwig

require_relative usa el directorio donde resida ese progtwig

Por ejemplo, si un progtwig está en ~/code y se llama 1.rb y usted ha hecho un cd para ese directorio

 cd ~/code 

e intentas ejecutar el progtwig ruby ​​con

 ruby 1.rb 

luego dentro de 1.rb

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

ambos funcionarán

Sin embargo, si estás en otro directorio, di

 cd ~/tmp 

e intentas ejecutar el progtwig con

 ruby ../1.rb 

entonces obtendrás un error como

 /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 `
'

cuando intentas usar

 require './2.rb' 

mientras que usando

 require_relative '3.rb' 

todavía funciona bien _porque la referencia (a 3.rb ) es relativa a qué directorio se encuentra el progtwig ( 1.rb ).

Las respuestas principales son correctas, pero profundamente técnicas. Para los más nuevos de Ruby–

  • require_relative probablemente se utilizará para traer el código de otro archivo que usted escribió.

por ejemplo, ¿qué ~/my-project/data.rb si tiene datos en ~/my-project/data.rb y desea incluirlos en ~/my-project/solution.rb ? en solution.rb agregaría require_relative 'data' .

Es importante tener en cuenta que estos archivos no necesitan estar en el mismo directorio. require_relative '../../folder1/folder2/data' también es válido.

  • require será probablemente utilizado para traer el código de una biblioteca que alguien más escribió.

por ejemplo, ¿qué active_support si desea utilizar una de las funciones auxiliares proporcionadas en la biblioteca active_support ? necesitarás instalar la gem con gem install activesupport y luego en el archivo require 'active_support' .

 require 'active_support/all' "FooBar".underscore 

Dicho de manera diferente–

  • require_relative requiere un archivo específicamente apuntado en relación con el archivo que lo llama.

  • require requiere un archivo incluido en $ LOAD_PATH.

Acabo de ver que el código RSpec tiene algún comentario sobre require_relative siendo O (1) constante y require ser O (N) lineal. Entonces, probablemente, la diferencia es que require_relative es el preferido que require .

Quiero agregar que al usar Windows puede usar require './1.rb' si el script se ejecuta localmente o desde una unidad de red mapeada, pero cuando se ejecuta desde una ruta UNC \ servername \ sharename \ folder necesita usar require_relative './1.rb' No me require_relative './1.rb' en la discusión que usar por otros motivos.