Какова лучшая практика, если я хочу require
относительный файл в Ruby, и я хочу, чтобы он работал как в 1.8.x, так и> = 1.9.2?
Я вижу несколько вариантов:
- просто сделай
$LOAD_PATH << '.'
и забудь все - делать
$LOAD_PATH << File.dirname(__FILE__)
require './path/to/file'
- проверьте, если
RUBY_VERSION
<1.9.2, то определитеrequire_relative
какrequire
, затем используйтеrequire_relative
везде, где это необходимо - проверьте,
require_relative
существует ли уже, если это так, попробуйте продолжить, как в предыдущем случае - используйте странные конструкции, такие как - увы, они не работают должным образом в Ruby 1.9, потому что, например:
require File.join(File.dirname(__FILE__), 'path/to/file')
$ cat caller.rb require File.join(File.dirname(__FILE__), 'path/to/file') $ cat path/to/file.rb puts 'Some testing' $ ruby caller Some testing $ pwd /tmp $ ruby /tmp/caller Some testing $ ruby tmp/caller tmp/caller.rb:1:in 'require': no such file to load -- tmp/path/to/file (LoadError) from tmp/caller.rb:1:in '<main>'
- Даже более странная конструкция: кажется, работает, но это странно и не совсем хорошо выглядит.
require File.join(File.expand_path(File.dirname(__FILE__)), 'path/to/file')
- Используйте гем backports - он довольно тяжелый, требует инфраструктуры rubygems и включает в себя множество других обходных путей, а я просто хочу
require
работать с относительными файлами.
В StackOverflow есть тесно связанный вопрос, который дает еще несколько примеров, но он не дает четкого ответа - что является лучшей практикой.
Есть ли какое-нибудь приемлемое, общепризнанное универсальное решение для запуска моего приложения на Ruby <1.9.2 и> = 1.9.2?
ОБНОВИТЬ
Пояснение: я не хочу просто отвечать, как «вы можете сделать X» - на самом деле, я уже упомянул большинство рассматриваемых вариантов. Я хочу обоснование , то есть, почему это лучшая практика, каковы ее плюсы и минусы и почему ее следует выбирать среди других.
require
иrequire_relative
?a.rb
и хотели, чтобы интерпретатор считывал и анализировал содержимое файлаb.rb
в текущем каталоге (обычно тот же каталог, что и вa.rb
), вы просто пишете,require 'b'
и это будет хорошо, поскольку путь поиска по умолчанию включает текущий каталог. В более современном Ruby 1.9 вам придется писатьrequire_relative 'b'
в этом случае, как еслиrequire 'b'
бы вы искали только стандартные пути к библиотекам. Это то, что нарушает прямую и обратную совместимость для простых сценариев, которые не будут установлены должным образом (например, сами сценарии установки ).backports
только дляrequire_relative
, см. Мой ответ ...Ответы:
Обходной путь для этого был только что добавлен к жемчужине 'aws', так что я подумала, что поделюсь этим, поскольку это было вдохновлено этим постом.
https://github.com/appoxy/aws/blob/master/lib/awsbase/require_relative.rb
Это позволяет вам использовать
require_relative
как в ruby 1.9.2 в ruby 1.8 и 1.9.1.источник
require_relative
функция включена в проект расширения базовых библиотек Ruby, который можно найти здесь: rubyforge.org/projects/extensions. У вас должна быть возможность установить ихgem install extensions
. Затем в вашем коде добавьте следующую строку передrequire_relative
: require 'extensions / all' (взято из поста Aurril здесь )Прежде чем перейти к 1.9.2, я использовал следующее для относительных потребностей:
Это немного странно в первый раз, когда вы видите это, потому что похоже, что в начале есть лишняя «...». Причина в том, что
expand_path
будет развернут путь относительно второго аргумента, а второй аргумент будет интерпретирован, как если бы это был каталог.__FILE__
Очевидно, это не каталог, но это не имеет значения, посколькуexpand_path
не имеет значения, существуют файлы или нет, он просто применяет некоторые правила для расширения таких вещей, как..
,.
и~
. Если вы можете преодолеть первоначальное "waitaminute, там нет лишнего..
?" Я думаю, что строка выше работает довольно хорошо.Если предположить, что
__FILE__
это так/absolute/path/to/file.rb
, то получится, чтоexpand_path
создаст строку/absolute/path/to/file.rb/../relative/path
, а затем применит правило, которое говорит, что..
следует удалить компонент пути перед ним (file.rb
в данном случае), возвращая/absolute/path/to/relative/path
.Это лучшая практика? Зависит от того, что вы подразумеваете под этим, но кажется, что это все в базе кода Rails, поэтому я бы сказал, что это, по крайней мере, достаточно распространенная идиома.
источник
У Кирки есть фрагмент для этого для 1.8. Вот:
Он просто использует ответы Тео, но вы все равно можете их использовать
require_relative
.источник
$RUBY_VERSION
или проверяя,require_relative
существует ли напрямую?require_relative
определено.Это не очень хорошая привычка безопасности: зачем открывать весь каталог?
Это не работает, если RUBY_VERSION <1.9.2
Вы уже ответили, почему это не лучшие варианты.
Это может работать, но есть более безопасный и быстрый способ: справиться с исключением LoadError:
источник
Я фанат использования гема rbx-require -lative ( источник ). Первоначально он был написан для Rubinius, но он также поддерживает MRI 1.8.7 и ничего не делает в 1.9.2. Требовать драгоценный камень просто, и мне не нужно бросать фрагменты кода в мой проект.
Добавьте его в свой Gemfile:
Тогда
require 'require_relative'
перед тобойrequire_relative
.Например, один из моих тестовых файлов выглядит так:
Это самое чистое решение из всех этих IMO, и камень не такой тяжелый, как бэкпорт.
источник
backports
Камень теперь позволяет загружать отдельные Backports.Вы могли бы тогда просто:
Это
require
не повлияет на более новые версии и не обновит другие встроенные методы.источник
Другой вариант - сообщить интерпретатору, какие пути искать
источник
Одна проблема, на которую я не обращал внимания в решениях на основе __FILE__, заключается в том, что они ломаются в отношении символических ссылок. Например, у меня есть:
Основной скрипт, точка входа, приложение foo.rb. Этот файл связан с ~ / Scripts / foo, который находится в моем $ PATH. Это требование require нарушается, когда я выполняю 'foo':
Поскольку __FILE__ - это ~ / Scripts / foo, поэтому приведенный выше оператор require ищет ~ / Scripts / foo / lib / someinclude.rb, которого, очевидно, не существует. Решение простое. Если __FILE__ является символической ссылкой, на нее необходимо разыменовать ссылку. Pathname # realpath поможет нам в этой ситуации:
источник
Если бы вы строили драгоценный камень, вы бы не хотели загрязнять путь загрузки.
Но в случае автономного приложения очень удобно просто добавить текущий каталог в путь загрузки, как вы это делали в первых 2 примерах.
Мой голос идет по первому варианту в списке.
Я хотел бы видеть некоторую основательную литературу по лучшим практикам Ruby.
источник
Я бы определил свой собственный,
relative_require
если он не существует (то есть под 1.8), а затем использовал бы один и тот же синтаксис везде.источник
Ruby on Rails способом:
источник