Почему Ruby 1.9.2 удаляет "." из LOAD_PATH, а какая альтернатива?
Последние изменения в Ruby 1.9.2 больше не делают текущий каталог .
часть вашего LOAD_PATH
, У меня есть нетривиальное количество Rake-файлов, которые предполагают, что .
является частью LOAD_PATH
, так что это сломало их (они сообщили "нет такого файла для загрузки" для всех операторов require, основанных на пути проекта). Было ли какое-то конкретное оправдание для этого?
Что касается исправления, добавив $: << "."
везде работает, но кажется невероятно хакерским, и я не хочу этого делать. Какой предпочтительный способ сделать мой Rakefiles 1.9.2+ совместимым?
7 ответов
Это считалось риском "безопасности".
Вы можете обойти это, используя абсолютные пути
File.expand_path(__FILE__) et al
или делать
require './filename' (ironically).
или с помощью
require_relative 'filename'
или добавив каталог "include"
ruby -I . ...
или то же самое, используя irb;
$irb -I .
Есть две причины:
- надежность и
- безопасность
Оба основаны на одном и том же базовом принципе: в общем, вы просто не можете знать, каков текущий каталог, когда ваш код выполняется. Это означает, что когда вам требуется файл и вы зависите от того, находится ли он в текущем каталоге, у вас нет возможности контролировать, будет ли этот файл вообще там или это тот файл, который вы действительно ожидаете там.
Как указывают другие ответы, это угроза безопасности, потому что .
в вашем пути загрузки ссылается на текущий рабочий каталог Dir.pwd
, а не каталог текущего загружаемого файла. Так что, кто бы ни выполнял ваш скрипт, он может изменить это просто cd
в другой каталог. Нехорошо!
Я использовал полные пути, построенные из __FILE__
как альтернатива.
require File.expand_path(File.join(File.dirname(__FILE__), 'filename'))
В отличие от require_relative
, это обратно совместимо с Ruby 1.8.7.
Использование require_relative 'file_to_require'
Добавьте это в свой код, чтобы сделать require_relative работу в 1.8.7:
unless Kernel.respond_to?(:require_relative)
module Kernel
def require_relative(path)
require File.join(File.dirname(caller.first), path.to_str)
end
end
end
'' Ваш путь уже давно считается плохим явлением в мире Unix (см., например, http://www.faqs.org/faqs/unix-faq/faq/part2/section-13.html). Я предполагаю, что ребята из Ruby были убеждены в том, что не стоит этого делать.
Я нашел, что это было смущающее изменение, пока я не понял пару вещей.
Вы можете установить RUBYLIB в свой.profile (Unix) и продолжить жизнь, как вы делали это раньше:
export RUBYLIB="."
Но, как уже упоминалось выше, это долгое время считалось небезопасным.
В подавляющем большинстве случаев вы можете избежать проблем, просто вызывая свои сценарии Ruby с префиксом "." например./scripts/server.
Как отметил Йорг Миттаг, я думаю, что вы хотите использовать require_relative
поэтому требуемый файл относится к исходному файлу require
декларация а не текущий рабочий реж.
Ваши зависимости должны быть относительно вашего файла сборки рейка.