2008-11-27 19 views
5

Imagine que tiene un foo.rb ejecutable, con las bibliotecas bar.rb organizada de la siguiente manera:Encontrando bibliotecas relativas al utilizar enlaces simbólicos al rubí ejecutables

<root>/bin/foo.rb 
<root>/lib/bar.rb 

En la cabecera de foo.rb se coloca el siguiente requiere traer funcionalidad en barra.rb:

require File.dirname(__FILE__)+"../lib/bar.rb" 

Esto funciona bien siempre que todas las llamadas a foo.rb sean directas. Si pone como decir $ HOME/proyecto, y enlace simbólico foo.rb en $HOME/usr/bin, entonces __FILE__ resuelve a $HOME/usr/bin/foo.rb, y por lo tanto no puede encontrar bar.rb en relación con el nombre de directorio para foo.rb.

Soy consciente de que los sistemas de envasado, tales como rubygems solucionar este problema mediante la creación de un espacio de nombres para buscar la biblioteca, y que también es posible ajustar la load_path usando $: incluir $HOME/project/lib, pero parece como si una solución más sencilla debe existe. ¿Alguien ha tenido experiencia con este problema y ha encontrado una solución o receta útil?

Respuesta

11

Sé que esto es las edades de edad, pero me acabo de encontrar esto:

require 'pathname' 
APP_ROOT = File.join(File.dirname(Pathname.new(__FILE__).realpath),'..') 
+0

Eso es definitivamente mejor, al menos son solo dos líneas. Todavía desafortunado que no hay una sola solución de línea. – dgtized

2

Puede utilizar esta función para seguir todos los enlaces simbólicos y devolver la ruta completa del archivo real:

def follow_link(file) 
    file = File.expand_path(file) 

    while File.symlink?(file) 
    file = File.expand_path(File.readlink(file), File.dirname(file)) 
    end 

    file 
end 

puts follow_link(__FILE__) 
+0

Supongo que funciona. No es realmente una solución feliz para algo que se supone que es el primero requerido en el archivo. No estoy contento con una solución que incluya ese fragmento en cada archivo para encontrar nuestro lugar desde el que se llamó. – dgtized

1

Probablemente vale la pena mencionar que + funciona bien con los objetos Pathname y también existe el método Kernel.Pathname, por lo que el código original de @ Burke podría hacerse aún más corto:

require 'pathname' 
APP_ROOT = Pathname.new(__FILE__).realpath + "../../lib" 
Cuestiones relacionadas