2009-05-26 14 views
27

¿Cuál es la mejor forma de administrar las rutas requeridas en un programa ruby?Ruby path management

Déjenme darles un ejemplo básico, considere una estructura como:

\MyProgram 

\MyProgram\src\myclass.rb 

\MyProgram\test\mytest.rb 

Si en mi prueba yo uso require '../src/myclass' entonces sólo puedo llamar a la prueba de \MyProgram\test carpeta, pero yo quiero ser capaz de llamarlo de cualquier camino!

La solución que se me ocurrió es definir en todos los archivos de origen de la línea siguiente:

ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(ROOT) y luego utilice siempre require "#{ROOT}/src/myclass"

¿Hay una mejor manera de hacerlo?

Respuesta

12

Aquí es una forma ligeramente modificada para hacerlo:

$LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), "..", "src")) 

anteponiendo el camino a la fuente a $ LOAD_PATH (alias $ :) que no tiene que suministrar la raíz etc. explícitamente cuando requiere su código, es decir, require 'myclass'

1

La respuesta de sris es el enfoque estándar.

Otra forma sería empaquetar el código como una joya. Entonces rubygems se encargará de asegurarse de que los archivos de su biblioteca estén en su camino.

9

El mismo, en mi humilde opinión menos ruidoso:

$:.unshift File.expand_path("../../src", __FILE__) 
require 'myclass' 

o simplemente

require File.expand_path "../../src/myclass", __FILE__ 

probado con ruby ​​1.8.7 y 1.9.0 en (Debian) Linux - por favor dime si funciona en Windows, también.

¿Por qué un método más simple (por ejemplo, 'use', 'require_relative' o sg como este) no está integrado en la lib estándar? ACTUALIZACIÓN: require_relative es allí desde 1.9.x

+0

Mientras que hace que mi columna vertebral cosquilleo, esta es la mejor opción que he visto para hacer esto _inside_ de ruby ​​hasta el momento. – Matt

+0

Es decir, prefiero agregar (no anteponer) la ruta a la ruta de Ruby, ya que no inadvertidamente pisar algo que existe en las bibliotecas de ruby ​​estándar. – Matt

+0

¿No quiso decir 'prefiero preceder (no agregar)' en su lugar? (en otras palabras: ¿realmente no quieres asegurarte de que tus cosas tengan prioridad?) Mi ejemplo original era '$: << newpath' que se agregaba, ahora lo arreglé por 'unshift', como lo hizo la respuesta anterior. Gracias – inger

0

Esto es lo que terminó con - una versión Rubí de una secuencia de comandos shell setenv:

# Read application config              
$hConf, $fConf = {}, File.expand_path("../config.rb", __FILE__) 
$hConf = File.open($fConf) {|f| eval(f.read)} if File.exist? $fConf 

    # Application classpath               
$: << ($hConf[:appRoot] || File.expand_path("../bin/app", __FILE__)) 

    # Ruby libs                  
$lib = ($hConf[:rubyLib] || File.expand_path("../bin/lib", __FILE__)) 
($: << [$lib]).flatten! # lib is string or array, standardize      

Luego sólo hay que asegurarse de que este script se llama una vez antes que nada, y no es necesario tocar los archivos fuente individuales.

puse algunas opciones dentro de un archivo de configuración, como la ubicación de las bibliotecas externas (no-GEM):

# Site- and server specific config - location of DB, tmp files etc. 
{ 
    :webRoot => "/srv/www/myapp/data", 
    :rubyLib => "/somewhere/lib", 
    :tmpDir => "/tmp/myapp" 
} 

Esto ha funcionado bien para mí, y puedo volver a utilizar el script setenv en múltiples proyectos simplemente cambiando los parámetros en el archivo de configuración. Una alternativa mucho mejor que los scripts de shell, IMO.

+0

@ j-g-faustus: "Fusionar __ FILE __ con el directorio de trabajo me asegura que puedo llamar desde cualquier lugar": File.expand_path (path, base) debería tener el mismo efecto. ¿Estás seguro de que la respuesta de Inger anterior no hizo el trabajo? ¿Qué te da esto? (póngalo en test.rb, por ejemplo): "pone File.expand_path" ../../src/myclass ", __ FILE __" – inger

+0

Tiene razón, File.expand_path hace lo mismo. He actualizado la publicación. Se vuelve un poco más limpio, gracias :) Aparte de eso, la principal diferencia es que este es un script separado que se ejecuta una vez al inicio de la aplicación, y no es necesario tocar los archivos fuente individuales. –

30

A partir de Ruby 1.9 se puede utilizar para hacer esto require_relative:

require_relative '../src/myclass' 

Si necesita esto para las versiones anteriores se puede obtener de la gema extensiones según this SO comment.

2
Pathname(__FILE__).dirname.realpath 

proporciona una ruta absoluta de una manera dinámica.

2

Uso siguiente código para exigir que todos los archivos "RB" en carpeta específica (=> Ruby 1.9):

path='../specific_folder/' # relative path from current file to required folder 

Dir[File.dirname(__FILE__) + '/'+path+'*.rb'].each do |file| 
    require_relative path+File.basename(file) # require all files with .rb extension in this folder 
end