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

302

¿Cuál es la diferencia entre require_relativey requireen Ruby?

agentbanks217
fuente
99
Antes de 1.9.2 no había necesidad de require_relative, porque el directorio actual del script estaba en $:. Ver stackoverflow.com/questions/2900370
Nakilon
1
require_relative requiere un archivo apuntado específicamente en relación con el archivo que lo llama. require requiere un archivo incluido en $ LOAD_PATH.
Donato
artículo útil sobre diferencias => medium.com/@ellishim/…
ahmed hamdy

Respuestas:

298

Solo mira los documentos :

require_relativecomplementa el método incorporado requirepermitiéndole cargar un archivo que es relativo al archivo que contiene la require_relativedeclaración.

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

require_relative "data/customer_data_1"
miku
fuente
28
¿Hay alguna diferencia entre require './file.rb'y require_relative 'file.rb'?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
69
@CiroSantilli Sí. require_relativele permite "cargar un archivo que es relativo al archivo que contiene la require_relativedeclaración ". Con require, ./indica una ruta que es relativa a su directorio de trabajo actual.
Ajedi32
17
Creo que es más importante tener en cuenta que require strsiempre buscará en los directorios en $ LOAD_PATH. Debe usarlo require_relativecuando el archivo que necesita cargar existe en algún lugar relativo al archivo que requiere la carga. Reserva requirepara dependencias "externas".
rthbound
97

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 plantea lo LoadErrorcontrario.

Esto implica que:

  • require_relative 'a'y require_relative './a'requiere relativo al archivo actual ( __FILE__).

    Esto es lo que desea usar cuando lo requiera 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")')aumenta LoadErrorporque __FILE__no está definido por dentro eval.

    Es por eso que no se puede usar require_relativeen las pruebas de RSpec, que se editan 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 require_relativeporque 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 /or ./o ../), que es siempre el caso File.expand_path.

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

  • require '/a.rb'y require_relative '/a.rb'ambos requieren el camino absoluto.

Leyendo la fuente

Cuando los documentos no están claros, le recomiendo que eche un vistazo a las fuentes (alternar la fuente en los documentos). En algunos casos, ayuda a entender 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__
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
fuente
74

De la API de Ruby :

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

Cuando utiliza require para cargar un archivo, generalmente está accediendo a la funcionalidad que se instaló correctamente y se hizo 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 a uso externo.

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

require_relative "data/customer_data_1" 

Como 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 requerimiento 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

svilenv
fuente
50

Resumen

Uso requirepara gemas instaladas

Usar require_relativepara archivos locales

requireusa tu $LOAD_PATHpara encontrar los archivos.
require_relativeusa la ubicación actual del archivo usando la instrucción


exigir

Requerir depende de que haya instalado (por ejemplo gem install [package]) un paquete en algún lugar de su sistema para esa funcionalidad.

Cuando lo use require, puede usar el ./formato " " para un archivo en el directorio actual, por ejemplo, require "./my_file"pero esa no es una práctica común o recomendada y debe usarla require_relativeen su lugar.

require_relative

Esto simplemente significa incluir el archivo 'relativo a la ubicación del archivo con la declaración require_relative'. En general, recomiendo que los archivos estén "dentro" del árbol de directorios actual en lugar de "arriba", por ejemplo , no use

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

(hasta 3 niveles de directorio) dentro del sistema de archivos porque eso tiende a crear dependencias innecesarias y frágiles. Sin embargo, en algunos casos, si ya está 'profundo' dentro de un árbol de directorios, puede ser necesario "subir y bajar" otra rama de árbol de directorios. Tal vez de manera más simple, no use require_relative para archivos fuera de este repositorio (suponiendo que esté usando git, que es en gran medida un estándar de facto en este momento, a fines de 2018).

Tenga en cuenta que require_relativeutiliza el directorio actual del archivo con la instrucción require_relative (por lo que no necesariamente es el directorio actual desde el que está utilizando el comando). Esto mantiene la require_relativeruta "estable", ya que siempre será relativa al archivo que lo requiere de la misma manera.

Michael Durrant
fuente
27

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

  • require_relative lo más probable es que se use para traer código de otro archivo que usted escribió.

por ejemplo, ¿qué pasa si tiene datos ~/my-project/data.rby desea incluirlos ~/my-project/solution.rb? en la solution.rbque se sumarí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 lo más probable es que se use para traer código de una biblioteca que alguien más escribió.

por ejemplo, ¿qué sucede si desea usar una de las funciones auxiliares proporcionadas en la active_supportbiblioteca? necesitará instalar la gema con gem install activesupporty luego en el archivo require 'active_support'.

require 'active_support/all'
"FooBar".underscore

Dicho de otra manera

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

  • requirerequiere un archivo incluido en el $LOAD_PATH.

halcón común
fuente
3
¿Cómo puedo votar esta respuesta y llevarla a la cima para que cada visitante de esta página de preguntas obtenga una respuesta clara y comprensible de inmediato sin romper sus cerebros?
TiredOfProgramming
16

Acabo de ver que el código de RSpec tiene algún comentario sobre require_relativeser O (1) constante y requireser O (N) lineal. Entonces, probablemente la diferencia es que require_relativees la preferida require.

mech
fuente
1
Interesante. Aterricé aquí buscando información sobre una comparación de velocidad. Pensé que require_relativeera más rápido porque el cargador no tiene que atravesar la ruta de carga en busca del archivo. Básicamente, require_relativeproporciona un enlace directo.
Clint Pachl
Discusión temprana sobre require_relative speed y el registro de cambios RSpec .
Clint Pachl
1

Quiero agregar que cuando use Windows puede usar require './1.rb'si el script se ejecuta localmente o desde una unidad de red asignada, pero cuando se ejecuta desde una \\servername\sharename\folderruta UNC , debe usarlo require_relative './1.rb'.

No me mezclo en la discusión sobre cuál usar por otras razones.

Peter
fuente
Quería saber cómo se carga el require_relativearchivo. ¿Podría
darme