Ruby Path Management - PullRequest
       10

Ruby Path Management

27 голосов
/ 26 мая 2009

Каков наилучший способ управления требуемыми путями в программе 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"

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

Ответы [ 7 ]

30 голосов
/ 10 сентября 2010

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

require_relative '../src/myclass'

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

12 голосов
/ 26 мая 2009

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

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

За счет добавления пути к исходному к $ LOAD_PATH (он же $ :) вам не нужно явно указывать корень и т. Д., Когда вам требуется код, т.е.

9 голосов
/ 07 ноября 2009

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

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

или просто

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

Протестировано с ruby ​​1.8.7 и 1.9.0 на (Debian) Linux - скажите, пожалуйста, работает ли оно и на Windows.

Почему более простой метод (например, 'use', 'require_relative' или sg вроде этого) не встроен в стандартную библиотеку lib? ОБНОВЛЕНИЕ: require_relative существует с 1.9.x

2 голосов
/ 03 января 2011

Используйте следующий код для запроса всех файлов "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
2 голосов
/ 01 декабря 2010
Pathname(__FILE__).dirname.realpath

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

1 голос
/ 26 мая 2009

ответом sris является стандартный подход.

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

0 голосов
/ 12 ноября 2009

Вот чем я закончил - 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                     

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

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

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

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

...