Подтвердить что ты не робот

Управление путями 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"

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

4b9b3361

Ответ 1

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

require_relative '../src/myclass'

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

Ответ 2

Вот несколько измененный способ сделать это:

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

Добавив путь к вашему источнику в $LOAD_PATH (aka $:), вам не нужно указывать корень и т.д. явно, когда вам нужен ваш код, т.е. require 'myclass'

Ответ 3

То же самое, менее шумное ИМХО:

$:.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

Ответ 4

Pathname(__FILE__).dirname.realpath

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

Ответ 5

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

Ответ 6

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

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

Ответ 7

Это то, что я закончил - Ruby-версия оболочки setenv script:

  # 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                     

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

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

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

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