Ruby
Язык программирования Ruby
Последние записи
INat::Get — ранняя альфа
— Я зделяль. ©
Итак, прошу любить и жаловать — INat::Get — софтина для получения и обработки данных с iNaturalist. Основное изначальное предназначение — подбивать всякую статистику для проектов на том же iNaturalist’е, но варианты использования гораздо шире.
Первым делом хочу отметить, что текущее состояние — это ранняя альфа. Я не рекомендую никому этим пользоваться иначе как из любопытства и желания поучаствовать. Тем не менее делаю пост уже сейчас в надежде, что любопытные желающие найдутся. Со своей стороны готов подробно отвечать на вопросы и учитывать пожелания.
Зачем?
iNaturalist предоставляет открытый доступ к огромному массиву наблюдений, а также по сути к постоянно актуализируему таксономическому справочнику (тут можно обсуждать нюансы, но для любительских целей это очень хорошие данные). Интерфейс самого сайта не покрывает и, конечно, не может покрывать все возможные варианты запросов и выборок, но мы можем получить сами данные через механизм выгрузок или посредством открытого API, и второй вариант богаче, гибче и вообще интересней.
Rack — основа веб-фреймворков в Ruby
Оригинал этой статьи опубликован в журнале «Системный администратор» №5 (150) за май 2015. Прошу обратить внимание на год — какие-то моменты могут расходиться с современными версиями языка и библиотек…
Библиотека Rack — простой объектный интерфейс для написания веб-приложений.
Слово «rack» в английском языке имеет множество значений, включая такие, как «пытка» и «разрушение»… Однако, надо полагать, название рассматриваемой библиотеки произошло от другой группы смыслов: «стойка», «штатив», «каркас» и т.д. Rack обеспечивает простой и в то же время удобный интерфейс, обеспечивающий взаимодействие между веб-сервером и приложением, позволяя программисту сосредоточиться исключительно на логике последнего.
Этот интерфейс достаточно низкоуровневый и не ограничивает разработчика каким-либо заранее заданным способом организации приложения и высокоуровневыми абстракциями. Соответственно, он и не предоставляет таких абстракций — это уже дело фреймворков, которые работают поверх него: Rails, Sinatra и других.
Средства самопознания в Ruby
Оригинал этой статьи опубликован в журнале «Системный администратор» №1-2 (146-147) за февраль 2015.
Что программа может знать о самой себе?
Практически все современные языки программирования содержат средства, позволяющие во время выполнения программы получить какие-то данные о структуре самой этой программы. В компилируемых языках такие возможности, как правило, ограничены и отключаемы, в целях оптимизации, в интерпретируемых же более обширны, поскольку эти данные все равно необходимы самому интерпретатору, соответственно, содержатся в памяти, и вопрос только в том, предоставлять ли к ним доступ языковыми средствами.
В данной статье я планирую рассмотреть те средства «самопознания», которые доступны для программ на Ruby.
Метапрограммирование в Ruby: разбор примера
Оригинал этой статьи опубликован в журнале «Системный администратор» №12 (145) за декабрь 2014.
Добавление собственных абстракций в объектную модель — это просто. И интересно.
Авторы книги «Programming Ruby: The Pragmatic Programmers’ Guide» называют метапрограммированием расширение и изменение абстракций языка (тогда как собственно программирование пользуется теми, что есть). Конечно, можно поспорить о том, что считать такой абстракцией, а что нет, однако нельзя не заметить, что в современных динамических языках, таких как Ruby или, например, Python, легко делаются некоторые вещи, которые в классических языках находились именно на языковом уровне и жестко определялись компилятором. Тут можно вспомнить, для примера, декораторы, о которых я писал в сентябре прошлого года1. И сейчас мы рассмотрим нечто подобное. В процессе я буду делать обобщающие отступления, переходя от частного примера к общим принципам программирования в Ruby.
-
Статья «Декораторы в Ruby». «Системный администратор» № 9 (130), сентябрь 2013. Стр. 68–71. ↩
Ruby и многозадачность
Оригинал этой статьи опубликован в журнале «Системный администратор» №3 (136) за март 2014.
В статье рассматриваются основные средства работы с потоками (threads) и процессами в языке и стандартной библиотеке Ruby
Немного о терминологии: англоязычный термин «thread» на русский переводится в двух вариантах — как «поток» и как «нить». Второй вариант точнее и не вызывает неоднозначности с потоками данных (streams), однако первый уже прижился в качестве основного. Кроме того, есть еще производные термины и варианты вроде «многонитевость» (или «многонитность»), но они мне не встречались и, честно говоря, режут глаз. Поэтому я буду использовать «поток».
Прежде, чем перейти к описаниям имеющегося инструментария, хотелось бы заметить, что Ruby создавался не как специальный язык параллельного программирования, при этом во время его создания и становления многозадачность уже стала привычной и необходимой. Из этих двух посылок, в общем-то, можно вывести текущую картину: никаких специфических концепций мы в нем не увидим, только поддержку привычной для всех языков общего назначения модели с некоторыми нюансами реализации.
Блоки и контекст в Ruby
Что стоит за конкретным идентификатором в данном окружении
Давайте разберемся с программным контекстом в Ruby: какие переменные и другие объекты доступны в конкретном месте
программы, и как интерпретатор их ищет? Что обозначает конкретный идентификатор, откуда он берется? Почему отсюда,
а не оттуда? И чему, наконец, в этом трижды перекинутом блоке будет равен self
?
Ruby очень гибок и позволяет переопределить так много, что, образно выражаясь, вы можете выстрелить себе в ногу из самой этой ноги. Картечью.
Распределенный Ruby
Оригинал этой статьи опубликован в журнале «Системный администратор» №12 (133) за декабрь 2013.
Технология распределенного Ruby, или dRuby (Distributed Ruby), позволяет вызывать методы объектов, находящихся в другом процессе и/или на другом компьютере. При этом установка соединения, передача необходимых данных и тому подобное — скрыты от программиста, и использование удаленных объектов мало чем отличается от работы с объектами, заданными внутри программы.
Это не единственная технология RPC, доступная при программировании на Ruby, однако более универсальные средства, такие как CORBA или XML-RPC, более сложны в использовании и требуют бо́льших накладных расходов (кроме того, поддержка CORBA не входит в стандартную библиотеку Ruby, соответственно, в сопровождении требует дополнительного внимания к совместимости версий и т.д.). В общем, если не требуется взаимодействие с программами, написанными на других языках, dRuby — очень хороший выбор, а с чем его едят и как правильно готовить, мы и рассмотрим в данной статье.
Декораторы в Ruby
Оригинал этой статьи опубликован в журнале «Системный администратор» №9 (130) за сентябрь 2013.
Как известно, в языке Python существует красивый механизм декораторов, расширяющих функционал объекта без изменения интерфейса. Это довольно мощное средство, попользоваться им удобно и приятно. Но вот проблема: наш язык программирования — Ruby!
На самом деле никакой проблемы нет, и в Ruby достаточно возможностей, чтобы решать подобные задачи не менее эффективно, чем в конкурирующих технологиях.
… … …
Универсальность всегда увеличивает сложность и накладные расходы. Так что мое мнение: жили мы без декораторов в Ruby и еще поживем. Тем не менее сама методика декорирования кода, безусловно, заслуживает внимания и может с успехом применяться в самых разных задачах.
Немного о dRuby
DRbObject не является DRbUndumped
Что это значит? Это значит, что если мы передаем посредством dRuby из процесса A процессу B объект, принадлежащий процессу C, при работе с ним B будет обращаться непосредственно к C. Если сможет, конечно, ведь легко может статься, что и B и C имеют доступ к A, но не имеют друг к другу. Тогда получим исключение.
Впрочем, нет никаких проблем заставить A проксировать этот объект для B: obj.extend(DRbUndumped)
на стороне A — и дело в шляпе.
Как проверить доступность DRbObject?
Встроенного метода, проверяющего, что объект DRbObject в действительности живой и готов к работе, почему-то нет. Но его легко написать:
Здесь мы пользуемся тем, что: а) DRb::DRbObject#respond_to?
всегда обращается к удаленному объекту, а не проверяет сам себя;
б) метод class
определен у каждого объекта, т.е. при доступности вызов вернет true
; и в) при недоступности генерируется вполне
конкретное исключение.
Это все, может быть, неочевидное, но вполне нормальное поведение. А вот следующее наблюдение мне представляется багом…
К какому сервису относится объект?
Предположим, у нас один процесс поднимает несколько сервисов DRb. Ну, например, один основной на TCP, а второй — управляющий на UnixSockets (см. мой гем drctrl). А затем обращается по DRb куда-то наружу и передает туда undumped-объект… Так вот: объект этот будет привязан не к тому протоколу, по которому идет обращение, а к последнему запущенному сервису.
Чтобы это исправить, нужно вручную выставить свойство DRb::primary_server
… Впрочем, в своем геме я сегодня это учел и исправил.
Четыре простеньких гема
Вот, наваял… Ссылки рядом с названием ведут на GitHub и RubyGems соответственно.
- set_version[gh][rg]
-
Развитие идеи, ранее начатой в геме
is-build
— автонумерация билдов. Теперь, если указать флаг „git: true
“, изменения в файле версий сразу же закоммитятся. Это довольно существенный момент, поскольку вручную я регулярно забывал это делать, в результате изменение версии попадало в какой-нибудь левый последующий коммит.В планах — сделать то же самое для Mercurial и SVN.
- current_spec[gh][rg]
-
Позволяет получить спецификацию текущего гема (т.е. того, откуда вызывается метод) и его версию. Понадобился как раз потому, что благодаря предыдущему полная информация о версии нигде в исходниках не хранится.
- wflt[gh][rg]
-
У интерпретатора Ruby есть прекрасная опция — „
-w
“ — показывать предупреждения. Для разработки очень полезно выставить ее по умолчанию, дабы писать «чисто» и обращать внимание на потенциальные проблемы сразу.Однако, предупреждения — это именно потенциальные проблемы, а не ошибки, и зачастую выдаются в случаях, когда код на самом деле правильный. Кроме того, предупреждения выдаются и на чужой код — в установленных гемах. Сообщения не по делу ужасно раздражают и сводят на нет психологическую пользу от контроля кода. Данный гем предназначен для того, чтобы их фильтровать. В принципе фильтры могут быть самые разные — для проверки используется «волшебный» оператор „
===
“, а в частности в репозиторий включен пример конфига, отфильтровывающий предупреждения в чужих исходниках, находящихся где-то внутри/usr
. - drctrl[gh][rg]
-
А этот гем уже посерьезней, хотя и тоже маленький. Он предназначен для управления скриптами, предоставляющими сервисы Distributed Ruby, и работает как такой же сервис, но только локально — через unix domain sockets. Позволяет останавливать и перезапускать сервисы.
В дальшейшем, возможно, добавятся еще какие-то управляющие функции того же рода.
Краткие инструкции на плохом английском можно прочитать в README-файлах на GitHub. Более подробная документация ждет своего часа.
PS. Все четыре гема требуют версии Ruby не ниже 2.0 — пора «закопать стюардессу».