Стучим по рельсам
Наш апрельский дайджест мы посвящаем Ruby on Rails. В фокусе патч для пользовательских пространств имён и руководство по развёртыванию RoR на современной OpenBSD. В качестве «изюминки» вспомнили забавный баг GitHub десятилетней давности. Приятного чтения!
Улучшение custom namespaces в Rails 7.1
Что происходит во время автоматической загрузки веб-приложения на Rails? Вначале система сканирует и загружает все поддиректории, находящиеся в директории приложения. Исключение составляют лишь assets, views и javascript. Если мы создадим там любую поддиректорию, то Rails обеспечит её автоматическую загрузку.
При этом стоит помнить, что директории работают в роли пространств имён, а имена файлов должны соответствовать константам, которые они определяют. Если у нас есть файл app/services/users/signup.rb, то внутри него должна быть определена константа Users::Signup. Предположим, что мы хотим, чтобы все сервисы в app/services были в пространстве имён Services.
Получается, надо определить константу Services::Users::Signup. Фактически придётся создать директорию app/services/services. Помещаем туда все наши сервисы и тогда они будут в пространстве имён Services. Не самое элегантное решение. Хотелось бы иметь способ сразу прописать константу вида Services::Users::Signup в файле app/services/users/signup.rb.
С выходом патча #47583 такая возможность появится. Никакой магии, исключительно настройка автозагрузчика:
# config/initializers/autoloading.rb
module Services; end
Rails.autoloaders.main.push_dir("#{Rails.root}/app/services", Services)
В предыдущих версиях (до Rails 7.1) требовалось дополнительно удалять директорию app/services из ActiveSupport::Dependencies.autoload_paths. Теперь же этого делать не придётся. За дополнительной информацией советуем заглянуть в комментарии к PR Improve support for custom namespaces.
Байка про nil
Новое — это хорошо забытое старое. Предлагаем отправиться в 2013 год и вспомнить любопытный баг GitHub. Тогда каждому пользователю без аватарки присваивалась аватарка из профиля разработчика Yehuda Katz. У этого разработчика идентификатор пользователя был равен 4. Ruby же присваивал идентификатору 4 значение nil, то есть отсутствие значения. Таким образом все пользователи без аватарки приравнивались к пользователю с идентификатором 4. Баг пофиксили, но вот для многих так и осталось тайной, почему так произошло.
Разгадка кроется в правильном понимании NIL. В мире Ruby nil представляет собой объект и имеет соответствующий идентификатор (ID). Если два объекта имеют один и тот же ID, значит они оба являются одним и тем же объектом в памяти. Это очень полезно для сравнения объектов, а также позволяет сборщику мусора лучше управлять выделением памяти. Вы можете самостоятельно взглянуть на некоторые зарезервированные ID через интерактивную оболочку irb:
В Matz Ruby Interpreter (MRI) значения true/false/nil (а также значения типа Fixnum) обрабатываются особым образом и реально для всех этих объектов в памяти нет структуры с данным. ID, в этом случае, будет указателем на место в памяти, который не будет пересекаться с кучей. За подробностями советуем заглянуть в статью Дхавала Сингха (Dhaval Singh).
Rails и Falcon на OpenBSD
OpenBSD существует уже 28 лет и до сих пор сохраняет статус свободной операционной системы. Концепция OpenBSD подразумевает полное отсутствие несвободных компонентов. Никакой код не может попасть в систему случайным образом, а любая неточность в документации немедленно исправляется. Несмотря на свою «самобытность» этот дистрибутив остаётся хорошим выбором для тех, у кого надёжность и безопасность стоит на первом месте.
Пару недель назад на Reddit появилась любопытная заметка, что в сервисе GitHub Gists (сервис наподобие Pastebin) выложили подробное руководство по развёртыванию Ruby on Rails + Falcon на OpenBSD. Автор руководства утверждает, что это самое чистое ядро, пользовательское пространство и синтаксис конфигурации. Предложенный им способ позволяет запускать веб-приложения от имени непривилегированного пользователя myappy. Такой пользователь владеет исключительно директориями tmp/ и log/ и не сможет сломать основную систему в случае взлома приложения.
Мы не поленились развернуть инстанс по этому руководству и нашли несколько проблемных моментов. Чтобы не подпортить впечатление, вспомните, что UNIX-системы чувствительны к регистру. Поэтому USER стоит заменить на user.
root# adduser -group user -batch myappy
Проверить, что непривилегированному пользователю назначены верные группы можно командой:
root# id -Gn myappy
myappy user
Точно также вторая команда с созданием привилегированного пользователя dev закончится ошибкой, если не поправить регистр (WHEEL заменить на wheel):
root# adduser -group wheel -batch dev
Когда мы ставим Ruby on Rails, система выдаст предупреждение, которое не стоит игнорировать, а именно создать символьные ссылки. Для версии 3.1.X эти команды выглядят так:
ln -sf /usr/local/bin/ruby31 /usr/local/bin/ruby
ln -sf /usr/local/bin/bundle31 /usr/local/bin/bundle
ln -sf /usr/local/bin/bundler31 /usr/local/bin/bundler
ln -sf /usr/local/bin/erb31 /usr/local/bin/erb
ln -sf /usr/local/bin/gem31 /usr/local/bin/gem
ln -sf /usr/local/bin/irb31 /usr/local/bin/irb
ln -sf /usr/local/bin/rdoc31 /usr/local/bin/racc
ln -sf /usr/local/bin/rake31 /usr/local/bin/rake
ln -sf /usr/local/bin/rdoc31 /usr/local/bin/rbs
ln -sf /usr/local/bin/rdoc31 /usr/local/bin/rdbg
ln -sf /usr/local/bin/rdoc31 /usr/local/bin/rdoc
ln -sf /usr/local/bin/ri31 /usr/local/bin/ri
ln -sf /usr/local/bin/typeprof31 /usr/local/bin/typeprof
Выделяем всю эту цепочку команд и вставляем в консоль. Без этого последующие команды просто не сработают. Перед тем, как выполнять множество команд, начинающихся на gem git_install, надо не забыть поставить git:
root# pkg_add git
Дальнейшие шаги по клонированию объёмного репозитория и установки гемов могут занять некоторое время, так что наберитесь терпения. Для удобства создания конфигов можно поставить привычный по Linux-системам редактор nano:
root# pkg_add nano
Подытожим: способ рабочий и результатом станет безопасный инстанс на базе OpenBSD. Возможно, кто-то однажды найдёт ваш сервер на OpenBSD с 30-летним аптаймом и приложением, которое будет работать, как ни в чём не бывало.
Интересно посмотреть
Мы рады делиться экспертизой наших специалистов. На YouTube-канале Evrone Academy появилось много новых обучающих видео по Ruby и Rails. Даже если вы давно пишете на Ruby, иногда полезно освежить знания и сверить их с другими экспертами. Ну а для новичков эти видео могут стать отличной отправной точкой.
Короткий и ёмкий формат занятий в 15-20 минут отлично подойдёт даже тем, у кого не слишком много свободного времени. Текстовые версии лекций доступны в нашем блоге на Хабре. Подписывайтесь и отправляйте эти видео своим друзьям, которые хотят начать изучать Ruby. И не забывайте нажать на «колокольчик», чтобы не пропустить новые видео.
Митапы
Ruby meetup №20
19 апреля 2023
Скоро мы встретимся с вами на замечательном Ruby Meetup. Программа мероприятия формируется и скоро станет доступна на странице мероприятия. Кстати, если вы не успели подать доклад, то можете это сделать прямо в режиме онлайн.
Теперь следить за митапами Evrone стало удобнее. В Telegram-канале Evrone meetups мы выкладываем анонсы с подробными описаниями докладов, а также студийные записи после мероприятий. А ещё, у нас можно выступить, мы поможем оформить вашу экспертизу в яркое выступление. Подписывайтесь и пишите @andrew_aquariuss, чтобы узнать подробности.
Вакансии
Удаленка / Офис
Evrone
Мы открыты для новых Ruby-разработчиков. В Evrone можно работать удалённо с первого дня, мы поддерживаем и оплачиваем участие в Open-source проектах и выступления на конференциях, а расти в грейдах можно с помощью честной системы проверки навыков и менторства.