Упрощение работы с путями в руби
Введение
Недавно наткнулся на интересное решение объединения путей в питоне. Вспомнил, как недавно приходилось довольно много работать с файлами и путями. И решил подбить всё в одну библиотеку (конечно же, беззастенчиво позаимствовав такой способ объединения путей). В статье более подробно хочу остановиться на пути к текущему файлу.
Текущий путь
Довольно часто встречающаяся конструкция, после объединения путей, в моём случае это:
File.dirname(__FILE__)Если делать класс для работы с путями файлов, то он должен наследоваться от String, чтобы можно было сделать:
File.open(filepath)А также должен уметь определять путь файла, в котором инициализируется или вызывается.
Начнём, конечно же, с тестов. Кроме всего прочего, я предпочитаю оперировать с развёрнутыми путями, т.к. если загружать библиотеку из разных мест, то пути могут не опознаваться как одинаковые, и интерпретатор ругается, например, на повторную инициализацию констант. Итак, тест с использованием RSpec:
describe FilePath do
it "should show correct current path" do
FilePath.current.should == File.expand_path(__FILE__)
end
endЕсли использовать __FILE__ внутри класса FilePath, то там окажется путь к файлу, в котором определяется класс.
Использование $0 так же не подходит, т.к. выдает путь только главного файла. В случае запуска теста $0 будет где-то в библиотеках.
Нам бы пригодилось что-нибудь вида:
eval("__FILE__", binding_of_caller)Но binding_of_caller работало с помощью бага, который уже давно исправлен, а Binding.of_caller выглядит очень громоздко (можно там кликнуть на ссылочку Source). Мало того, что он ломает trace_func, так он требует, чтобы метод, в котором он используется, вызывали только внутри метода.
Можно ещё передавать внутрь метода пустой Proc, вытаскивая его binding, но требовать это от человека, использующего библиотеку для упрощения жизни, как-то нелепо.
Решение
На помощь спешит Kernel.caller, знакомый нам по трейсам ошибок. Если разобраться, как он работает, то решение приходит сразу:
caller(1)[0].split(":")[0]Остальное можно посмотреть в исходниках file_path@github. Когда соберётся джем-библиотека, я обновлю инструкции и опубликую rdoc. Вдруг кому пригодится!
Комментарии:
Sergey Kruk 07 июля 2009, 11:14
вроде не то :)
Anonymous 07 июля 2009, 10:20
что я не врублюсь, разве это не то?
http://www.ruby-doc.org/stdlib/libdoc/pathname/rdoc/index.html