Ruby: Настройка окружения
Теория: Бандлер
По историческим причинам, утилита gem не умеет управлять зависимостями конкретного проекта. С ее помощью нельзя легко указать зависимости, поставить их одной командой и разделить на основные зависимости и зависимости для разработки. Поэтому ее, в основном, используют для установки гемов, которые нужны в системе глобально, например линтера.
Для полноценного управления зависимостями используется гем bundler, который включен в RubyGems и поставляется с ним по умолчанию. В этом уроке, мы научимся подключать его к проекту и разберемся с некоторыми особенностями работы.
Установка зависимостей
Работа с Bundler начинается с создания файла Gemfile в котором указываются зависимости. Сам файл использует Ruby-код для своего описания:
Когда в файл добавлены зависимости, нужно выполнить их установку:
Во время установки bundler создаст файл Gemfile.lock, в котором фиксируются версии всех зависимостей включая транзитивные. Любой последующий запуск команды install будет ориентироваться на версии указанные в этом файле. Сам lock-файл должен храниться в git-репозитории.
Благодаря lock-файлу, в Ruby не принято указывать версии гемов в Gemfile, они и так зафиксированы. Технически указать версии можно и иногда это бывает важно, когда, по какой-то причине нужно зафиксировать версию:
Для обновления зависимостей используется команда bundle update:
Добавляют гемы прямым прописыванием в файле Gemfile. В Bundler есть команда добавления гема, но она мало полезна из-за того, как Bundler работает с разделением сред.
Группировка гемов
В Bundler нет предустановленного разделения на продакшен- и девелопмент-зависимости, как, например, в JavaScript. Единственное, что он предоставляет, это механизм группировки гемов.
Группировка - обобщенный механизм, с его помощью можно создавать любое количество сред, в которых мы хотим запускать код. В примере выше есть не только продакшен (все что вне групп) и разработка, но и группа для тестов. Эти зависимости используются и подключаются только во время запуска тестов.
По умолчанию команда bundle install устанавливает все гемы, включая те что указаны внутри групп. Чтобы установить только конкретную группу, ее можно указать явно:
Гемы указанные вне групп будут установлены в любом случае, так как, по смыслу, они нужны всем.
Сами гемы устанавливаются в стандартные пути RubyGems, а не локально в проект. Это позволяет экономить место если проектов на Ruby много, но не подходит в том случае, если мы работаем, например, в Docker. Поэтому путь для установки гемов иногда меняют на vendor/bundle.
Эта команда создаст файл .bundle/config, в котором будет указан путь установки. Bundler использует эту конфигурацию во время своей работы.
Интеграция в проект
Bundler появился намного позже чем RubyGems, поэтому он не включается автоматически. Для подключения Bundler, во входном файле нужно добавить сверху такой код:
В этом случае в пути загрузки добавятся все гемы из всех групп. Если нужно указать конкретные группы, то код меняется на такой:
Когда гемов становится много, то постоянные включения зависимостей начинают сильно разрастаться. Bundler может взять эту работу на себя и включить все нужные зависимости сразу во время настройки:
В целом, прямая работа с подключением Bundler нужна редко. В прикладных проектах типа Rails, весь процесс инициализации скрыт от программиста. А для библиотек используется автоматическая генерация кода.

