2009-05-07 12 views
79

He visto dos técnicas comúnmente usadas para agregar el directorio del archivo que se está ejecutando actualmente al $ LOAD_PATH (o $ :). Veo las ventajas de hacer esto en caso de que no estés trabajando con una gema. Uno parece más detallado que el otro, obviamente, pero ¿hay alguna razón para ir uno sobre el otro?

El primer método, prolijo (podría ser una exageración):

$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__))) 

y el rápido y sucio, más sencillo,:

$:.unshift File.dirname(__FILE__) 

algún motivo para ir con uno sobre el otro?

+1

A ** ** ligeramente versión menos detallado de la prolija es:. 'File.expand_path (File.dirname (__ __ ARCHIVO)) pulse {| pwd | $ LOAD_PATH.unshift (PWD) a menos que $ LOAD_PATH.include? (PWD)} ' –

+0

¿qué hay de la cláusula "salvo"? ¿Cómo pueden los dos anteriores ser equivalentes? – inger

+0

Como alguien que vino aquí para tratar de entender cómo usar esto, es súper críptico. No veo de dónde viene el nombre del directorio en los ejemplos. Agradecería si alguien pudiera aclarar esto. – SlySherZ

Respuesta

47

Yo diría que vaya con $:.unshift File.dirname(__FILE__) sobre el otro, simplemente porque he visto mucho más uso del mismo en el código que el $LOAD_PATH, ¡y es más corto también!

+0

Cuando comencé con Ruby, obviamente pensé que $ LOAD_PATH era mejor. Pero una vez que se haya graduado del estado de principiante, solo usaría $ LOAD_PATH si estuviera tratando de hacer que mi código sea más legible para un principiante. Meh es un intercambio. Depende de qué tan "público" sea el código, siempre que el uso de la memoria sea el mismo para cada uno, lo que supongo que es esencialmente. –

+0

¿Qué tal si comprueba si $: ya contiene la entrada? – inger

+4

Depende de la guía de estilo que sigas para tu proyecto. La popular [Guía de estilo Ruby] (https://github.com/bbatsov/ruby-style-guide#syntax) dice "Evitar el uso de variables especiales estilo Perl (como $ :, $ ;, etc.). Son bastante críptico y se desaconseja su uso en cualquier cosa que no sean guiones de una sola línea ". – bobmagoo

18

No soy demasiado aficionado a la manera 'rápida y sucia'. Cualquier persona nueva en Ruby se preguntará qué es $:..

Encuentro esto más obvio.

libdir = File.dirname(__FILE__) 
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir) 

O si me importa tener la ruta completa ...

libdir = File.expand_path(File.dirname(__FILE__)) 
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir) 

ACTUALIZACIÓN 2009/09/10

En los últimos tiempos he estado haciendo lo siguiente:

$:.unshift(File.expand_path(File.dirname(__FILE__))) unless 
    $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__))) 

Lo he visto en un montón de diferentes proyectos de ruby, mientras que b haciendo fila en GitHub.

¿Parece ser la convención?

+0

@LukeAntins, esto es realmente genial, pero ¿dónde debería "arrancar" load_path en la aplicación? – gaussblurinc

+0

@gaussblurinc En algún lugar 'cerca de la parte superior' de su lib/aplicación, pero realmente depende. Si tenía un archivo 'bin' que siempre estaba relacionado con su' código' y solo lo ejecutaba el archivo 'bin' ... bootstrap en el bin.Si tiene una biblioteca, entonces el bootstrap en la parte superior de usted es el código de la biblioteca como en 'lib/code.rb' para tener acceso a todo bajo' lib/code/'. Espero que este paseo ayude! –

+0

RuboCop me informa que '__dir__' se puede usar para obtener una ruta al directorio del archivo actual. – Raphael

136

La ruta de carga de Ruby se ve comúnmente escrito como $: pero solo porque es corto, no lo hace mejor. Si prefieres la claridad a la astucia, o si la brevedad por sí misma te produce comezón, no necesitas hacerlo solo porque todos los demás lo son. Da la bienvenida a ...

$LOAD_PATH 

... y decir adiós a ...

# I don't quite understand what this is doing... 
$: 
+25

Además, es mucho más difícil buscar cadenas como "$:" que contengan solo símbolos. – DSimon

+35

@DSimon No * Google * for '$:', use http://www.symbolhound.com/ – Sparhawk

7

Si escribe script/console en su proyecto Rails y entra $:, obtendrá una matriz que incluye todos los directorios necesarios para cargar Ruby. La conclusión de este pequeño ejercicio es que $: es una matriz. Siendo así, puede realizar funciones en él como anteponer otros directorios con el método unshift o el operador <<. Como dijiste en tu declaración, $: y $LOAD_PATH son lo mismo.

La desventaja de hacerlo de la manera rápida y sucia como mencionó es esto: si ya tiene el directorio en su ruta de inicio, se repetirá.

Ejemplo:

tengo un plugin que creé llamado TODO. Mi directorio está estructurado así:

 
/---vendor 
    | 
    |---/plugins 
     | 
     |---/todo 
       | 
       |---/lib 
        | 
        |---/app 
          | 
          |---/models 
          |---/controllers 
       | 
       |---/rails 
        | 
        |---init.rb 

En el archivo init.rb entré en el siguiente código:

## In vendor/plugins/todo/rails/init.rb 
    %w{ models controllers models }.each do |dir| 
     path = File.expand_path(File.join(File.dirname(__FILE__), '../lib', 'app', dir)) 
     $LOAD_PATH << path 
     ActiveSupport::Dependencies.load_paths << path 
     ActiveSupport::Dependencies.load_once_paths.delete(path) 
    end 

Nota cómo le digo al bloque de código para realizar las acciones dentro del bloque a las cuerdas 'modelos', 'controladores' y 'modelos', donde repito 'modelos'. (FYI, %w{ ... } es solo otra manera de decirle a Ruby que mantenga una variedad de cadenas). Cuando corro script/console, escribo lo siguiente:

>> puts $: 

Y escribo esto para que sea más fácil de leer el contenido de la cadena. La salida que recibo es:

 
... 
... 
./Users/Me/mySites/myRailsApp/vendor/plugins/todo/lib/app/models 
./Users/Me/mySites/myRailsApp/vendor/plugins/todo/lib/app/controllers 
./Users/Me/mySites/myRailsApp/vendor/plugins/todo/lib/app/models 

Como se puede ver, aunque esto es tan simple un ejemplo que podría crear mientras se utiliza un proyecto que estoy trabajando actualmente, si no se tiene cuidado la manera rápida y sucia conducirá a caminos repetidos. La forma más larga verificará las rutas repetidas y se asegurará de que no ocurran.

Si usted es un programador experimentado rieles, es probable que tenga una muy buena idea de lo que está haciendo y es probable que no cometa el error de repetir caminos. Si eres un novato, iría por el camino más largo hasta que entiendas realmente lo que estás haciendo.

+0

su respuesta fue muy útil y también bien explicada. Edición sugerida: el método 'load_paths' y' load_once_paths.delete' han quedado obsoletos. Sería útil actualizar las líneas que se refieren a ellos como: 'ActiveSupport :: Dependencies.autoload_paths << path' ' ActiveSupport :: Dependencies.autoload_once_paths.delete (path) ' – Uzzar

4

mejor que he encontrado para añadir un directorio a través de la ruta relativa al usar Rspec. Me parece lo suficientemente detallado, pero también sigue siendo un buen trazador de líneas.

$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) 
Cuestiones relacionadas