Почему Ruby 1.9.2 удаляет "." от LOAD_PATH, и какова альтернатива?

Последние изменения в Ruby 1.9.2 больше не делают текущий каталог . частью вашего LOAD_PATH. У меня есть нетривиальное число Rakefiles, которые предполагают, что . является частью LOAD_PATH, так что это сломало их (они сообщили, что "нет такого файла для загрузки" для всех требующих операторов, основанных на пути к проекту). Было ли какое-то оправдание для этого?

Что касается исправления, то добавление $: << "." везде работает, но кажется невероятно взломанным, и я не хочу этого делать. Какой предпочтительный способ сделать мой Rakefiles 1.9.2+ совместимым?

Ответ 1

Это считалось "угрозой безопасности".

Вы можете обойти это, используя абсолютные пути

File.expand_path(__FILE__) et al

или делать

require './filename' (ironically).

или используя

require_relative 'filename'

если использовать irb

$irb -I .

Ответ 2

Есть две причины:

  • надежность и
  • Безопасность

Оба основаны на одном и том же базовом принципе: в общем, вы просто не можете знать, что представляет собой текущий каталог, когда ваш код запущен. Это означает, что, когда вам нужен файл и зависит от его наличия в текущем каталоге, у вас нет способа контролировать, будет ли этот файл даже там, или это тот файл, который вы действительно ожидаете там.

Ответ 3

Как указывают другие ответы, это риск безопасности, поскольку . в вашем пути загрузки относится к текущему рабочему каталогу Dir.pwd, а не к каталогу текущего загружаемого файла. Поэтому любой, кто выполняет ваш script, может изменить это просто cd ing в другой каталог. Нехорошо!

В качестве альтернативы я использовал полные пути, построенные из __FILE__.

require File.expand_path(File.join(File.dirname(__FILE__), 'filename'))

В отличие от require_relative, это обратно совместимо с Ruby 1.8.7.

Ответ 4

Используйте 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

Ответ 5

'' на вашем пути уже давно считается плохой в мире Unix (см., например, http://www.faqs.org/faqs/unix-faq/faq/part2/section-13.html). Я предполагаю, что люди Руби были убеждены в мудрости этого не делать.

Ответ 6

Как отметил Йорг W Миттаг, я думаю, что вы хотите использовать require_relative, поэтому требуемый файл относится к исходному файлу объявления require, а не к текущему рабочему директорию.

Ваши зависимости должны быть относительно вашего файла сборки rake.

Ответ 7

Я обнаружил, что это смешение изменений, пока я не понял пару вещей.

Вы можете установить RubyLIB в свой .profile(Unix) и продолжить жизнь, как вы это делали раньше:

export RUBYLIB="."

Но, как упоминалось выше, долгое время считалось небезопасным.

В подавляющем большинстве случаев вы можете избежать проблем, просто называя свои рубиновые скрипты с добавленным ".". например./scripts/server.