2009-05-26 2 views
27

Каков наилучший способ управления требуемыми путями в рубиновой программе?Управление путями Ruby

Позвольте мне привести простой пример, рассмотрим структуру типа:

\MyProgram 

\MyProgram\src\myclass.rb 

\MyProgram\test\mytest.rb 

Если в моем тесте я использую require '../src/myclass' то я могу назвать только тест из \MyProgram\test папки, но я хочу, чтобы быть в состоянии назвать его с любого пути!

Решение, которое я придумал, чтобы определить, во всех исходных файлах следующей строки:

ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(ROOT) и затем всегда использовать require "#{ROOT}/src/myclass"

Есть ли лучший способ сделать это?

ответ

12

Вот немного модифицированный способ сделать это:

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

По предваряя путь к источнику до $ LOAD_PATH (ака $ :) Вы не должны поставлять корень и т.д. явно при требуется ваш код, то есть require 'myclass'

1

Ответ sris - стандартный подход.

Другой способ заключается в том, чтобы упаковать ваш код в качестве драгоценного камня. Затем rubygems позаботятся о том, чтобы ваши файлы библиотеки находились на вашем пути.

9

То же, менее шумными ИМХО:

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

или просто

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

Испытано с рубином 1.8.7 и 1.9.0 на Debian (Linux) - пожалуйста, скажите мне, если он работает на Windows тоже.

Почему более простой метод (например, 'use', 'require_relative' или sg как это) не встроен в стандартную библиотеку lib? UPDATE: require_relative находится там с 1.9.x

+0

Хотя это делает мой позвоночник покалывание, это лучший вариант, я видел для этого _inside_ рубина до сих пор. – Matt

+0

То есть, я предпочитаю добавлять (не дописывать) путь к пути ruby, так как вы случайно не топаете над тем, что существует в стандартных библиотеках ruby. – Matt

+0

Разве вы не имели в виду «Предпочитаю вместо этого добавлять (вместо добавления)»? (другими словами: разве вы не хотите, чтобы ваши вещи имели приоритет?) Мой первоначальный пример был «$: << newpath», который был добавлен, теперь он исправлен «unshift», как это сделал предыдущий ответ. Спасибо – inger

0

Это то, что я закончил с - версией Ruby-скрипта в 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      

Тогда мне просто нужно, чтобы убедиться, что этот скрипт вызывается один раз прежде всего, и не нужно касаться отдельных исходных файлов.

Я положил некоторые опции в файле конфигурации, как расположение внешних (не гем) библиотеки:

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

Это работает хорошо для меня, и я могу повторно использовать скрипт SETENV в нескольких проектах просто изменив параметры в файле конфигурации. Это гораздо лучшая альтернатива, чем shell-скрипты, IMO.

+0

@ j-g-faustus: «Слияние __ FILE __ с рабочим каталогом гарантирует, что я могу вызвать его из любого места»: File.expand_path (путь, база) должен иметь тот же эффект. Вы уверены, что ответ Гидера выше не выполнил эту работу? Что это дает вам? (например, поставить его в test.rb): «puts File.expand_path» ../../src/myclass », __ FILE __» – inger

+0

Вы правы, File.expand_path делает то же самое. Я обновил сообщение. Это становится немного чище, спасибо :) Кроме того, основное отличие состоит в том, что это отдельный сценарий, который запускается один раз при запуске приложения, и мне не нужно прикасаться к отдельным исходным файлам. –

30

На Ruby 1.9 вы можете использовать require_relative сделать это:

require_relative '../src/myclass' 

Если вам это нужно для более ранних версий вы можете получить его из камня расширений согласно this SO comment.

2
Pathname(__FILE__).dirname.realpath 

обеспечивает абсолютный путь динамическим способом.

2

Используйте следующий код, чтобы требовать все «Р.Б.» файлов в определенной папке (=> 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 

 Смежные вопросы

  • Нет связанных вопросов^_^