2010-08-27 17 views
22

Tengo una pregunta más conceptual en Rails ... o Ruby para ese asunto:¿Cuándo llamar a un "requerir" en Rails?

Es mejor llamar a un requerimiento justo antes del método que lo necesita, group my require al comienzo de la clase o en algún lugar de un inicializador cuando arranca Rails?

¿Importa desde el punto de vista del rendimiento? Desde el punto de vista de la legibilidad? ¿Hace una diferencia si uso Rails 3?

Gracias!

Respuesta

19

Si le preocupa el rendimiento, debe solicitar las cosas en el contexto de dónde se necesitan, de modo que si esa parte del código no se ejerce, la biblioteca no se carga. Cualquier llamada subsiguiente al require no tendrá efecto ya que el archivo ya se ha cargado. Esto termina pareciéndose a algo en la línea de:

if (user.using_openid?) 
    require 'openid' 

    # ... Do OpenID stuff 
end 

Si bien esto es más eficiente en términos de recursos, puede hacer que sea muy difícil determinar las dependencias de su aplicación. Declarar estos por adelantado deja en claro a otras personas que mantienen el software. Tenga en cuenta que "otras personas" siempre incluye su ser futuro cuando haya olvidado algunos detalles de su aplicación.

Está técnicamente permitido solicitar cualquier cosa en cualquier momento, tarde o temprano, pero declarar sus requisitos por adelantado es mejor desde una perspectiva de diseño. Si encuentra que hay un elemento que se usa solo de forma intermitente y requiere una cantidad inusual de tiempo o memoria para cargarse, entonces probablemente debería documentarlo por adelantado en su archivo de requisitos. Por ejemplo:

require 'library1' 
require 'library2' 
require 'library3' 
require 'library4' 
require 'library5' 

# Other libraries loaded as required: 
# * slowimagelibrary 
# * slowencryptionlibrary 
# * openid 

Podría decirse que esto es un problema menor con bundler porque puede tener sus gemas declarados por adelantado de manera más formal y la require llamada real puede venir más adelante.

+2

Gracias tadman, esto está en línea con lo que estaba pensando. Conclusión: la legibilidad es más importante que el rendimiento, excepto cuando se requiere pesado. – Cimm

4

Si considera el ruby ​​vainilla, 'require' se usa principalmente en las primeras líneas, porque entonces está seguro de que tiene acceso a lo que necesita, y es más fácil encontrar y leer qué dependencia necesita.

Hay algunos casos en los que desea cargar una gema solo en un método, porque esto realmente no es necesario para que su script funcione (por ejemplo, una visualización opcional).

Con rieles, creo que depende de lo que quieras hacer.

Si usa Bundler, puede asumir que su gema ha sido 'requerida' (por supuesto, puede anular lo que se requiere con la opción: require).

Si es algo que desea cargar automáticamente cuando se inicia el servidor (como validadores o creadores de formularios), entonces debería ver cómo hacerlo con la configuración (rutas_autoload y rutas_carga_eager).

require también se puede utilizar para cargar solo una parte de una gema, como una extensión de ella. Entonces, por supuesto, se requiere donde está la configuración.

Es posible que le preocupe si trabaja en un entorno de subprocesos múltiples, ya que hay algunos problemas con eso. A continuación, debe asegurarse de que todo esté cargado antes de ejecutar sus hilos. (Algo así como la constante de clase está cargado, pero aún no hay métodos, había un buen artículo pero no puedo encontrarlo más).

Es posible que también quiera probar {Module, Kernel}.autocarga, Rails lo usa ampliamente para cargar solo lo que se necesita cuando se accede (pero se ve bastante feo).

También puede hackear usted mismo con const_missing (por lo que esto puede hacer la carga lenta, si acepta una estructura). Este es un ejemplo simple (no será apropiado para clases anidadas).

def Object.const_missing c 
    if (file = Dir["#{c.downcase}.rb"]).size == 1 
    require_relative(file) 
    end 
    if const_defined? c 
    const_get c 
    else 
    super # Object < Module 
    end 
end 

Sobre el rendimiento, una llamada a requerir es relativamente caro, así que si usted sabe que va a utilizarlo, lo hacen sólo una vez, si es posible. Sin embargo, para administrar dependencias complejas dentro de su proyecto, es posible que necesite solicitar archivos relativos. Entonces require_relative es el camino a seguir en 1.9.

Por último, para un proyecto, recomendaría requerir todo en el archivo principal en lib /, con alguna expresión Dir["**/*.rb"]. Rara vez necesitaría require_relative, porque solo es necesario si hace referencia en el cuerpo de la clase a otra constante (no se resuelven todos los contenidos de los métodos, por lo que no hay ningún problema con eso).

Otra solución sería definir estas constantes en su archivo principal, también le daría una idea de la estructura.

Cuestiones relacionadas