2008-11-27 8 views
5

Imaginez que vous avez un foo.rb exécutable, avec les bibliothèques bar.rb dans la pondus manière suivante:Recherche de bibliothèques relatives lors de l'utilisation des liens symboliques à ruby ​​executables

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

Dans l'en-tête de foo.rb vous placez le suivant besoin d'apporter des fonctionnalités dans bar.rb:

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

Cela fonctionne très bien tant que tous les appels à foo.rb sont directs. Si vous mettez par exemple $ HOME/project et symlink foo.rb dans $HOME/usr/bin, alors __FILE__ résout en $HOME/usr/bin/foo.rb, et est donc incapable de localiser bar.rb par rapport au nom de répertoire pour foo.rb.

Je me rends compte que les systèmes d'emballage tels que rubygems résoudre ce problème en créant un espace de noms pour rechercher la bibliothèque, et qu'il est également possible de régler le load_path en utilisant $: pour inclure $HOME/project/lib, mais il semble que si une solution plus simple devrait exister. Est-ce que quelqu'un a eu de l'expérience avec ce problème et a trouvé une solution ou une recette utile?

Répondre

11

Je sais que c'est vieux âges, mais je viens de trouver ceci:

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

C'est certainement mieux, au moins c'est juste deux lignes. Toujours malheureux qu'il n'y ait pas une seule solution de ligne. – dgtized

2

Vous pouvez utiliser cette fonction pour suivre les liens symboliques et retourner le chemin complet du fichier réel:

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

Je suppose que cela fonctionne. Pas vraiment une solution heureuse pour quelque chose qui est censé être le premier besoin dans le fichier. Je ne suis pas content d'une solution qui inclut cet extrait dans tous les fichiers afin de trouver l'endroit d'où il a été appelé. – dgtized

1

Il vaut la peine de mentionner que + fonctionne bien avec Pathname objets et aussi il y a la méthode Kernel.Pathname, donc le code original de @ Burke pourrait être rendu encore plus court:

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