Зарегистрируйтесь, чтобы продолжить обучение

Бандлер Ruby: Настройка окружения

По историческим причинам, утилита gem не умеет управлять зависимостями конкретного проекта. С ее помощью нельзя легко указать зависимости, поставить их одной командой и разделить на основные зависимости и зависимости для разработки. Поэтому ее, в основном, используют для установки гемов, которые нужны в системе глобально, например линтера.

Для полноценного управления зависимостями используется гем bundler, который включен в RubyGems и поставляется с ним по умолчанию. В этом уроке, мы научимся подключать его к проекту и разберемся с некоторыми особенностями работы.

Установка зависимостей

Работа с Bundler начинается с создания файла Gemfile в котором указываются зависимости. Сам файл использует Ruby-код для своего описания:

# В реальности тут вызываются функции
# source(), gem() и тому подобные

# Источник гемов
source 'https://rubygems.org'

gem 'rails'
gem 'rack'
gem 'puma'
gem 'ransack'

Когда в файл добавлены зависимости, нужно выполнить их установку:

# В директории с Gemfile
bundle install

Во время установки bundler создаст файл Gemfile.lock, в котором фиксируются версии всех зависимостей включая транзитивные. Любой последующий запуск команды install будет ориентироваться на версии указанные в этом файле. Сам lock-файл должен храниться в git-репозитории.

Благодаря lock-файлу, в Ruby не принято указывать версии гемов в Gemfile, они и так зафиксированы. Технически указать версии можно и иногда это бывает важно, когда, по какой-то причине нужно зафиксировать версию:

# ~> означает что фиксируется major и minor, а patch может обновиться
# https://semver.org/
gem 'rails', '~> 6.1'

Для обновления зависимостей используется команда bundle update:

bundle update

Добавляют гемы прямым прописыванием в файле Gemfile. В Bundler есть команда добавления гема, но она мало полезна из-за того, как Bundler работает с разделением сред.

Группировка гемов

В Bundler нет предустановленного разделения на продакшен- и девелопмент-зависимости, как, например, в JavaScript. Единственное, что он предоставляет, это механизм группировки гемов.

# Гемы указанные вне групп ставятся всегда

gem 'rails'
gem 'pg'

# имя группы выбирается произвольно
# стандартных имен групп нет
group :development do
  gem 'rubocop'
  gem 'solargraph'
  gem 'spring'
end

group :test do
  gem 'capybara'
  gem 'webdrivers'
end

# Можно даже так
# Зависимости которые будут использоваться
# и для :test среды и для :development
group :test, :development do
  gem 'capybara'
  gem 'webdrivers'
end

Группировка - обобщенный механизм, с его помощью можно создавать любое количество сред, в которых мы хотим запускать код. В примере выше есть не только продакшен (все что вне групп) и разработка, но и группа для тестов. Эти зависимости используются и подключаются только во время запуска тестов.

По умолчанию команда bundle install устанавливает все гемы, включая те что указаны внутри групп. Чтобы установить только конкретную группу, ее можно указать явно:

# Так
bundle install --with development
# Или так
bundle install --with test,development

Гемы указанные вне групп будут установлены в любом случае, так как, по смыслу, они нужны всем.

Сами гемы устанавливаются в стандартные пути RubyGems, а не локально в проект. Это позволяет экономить место если проектов на Ruby много, но не подходит в том случае, если мы работаем, например, в Docker. Поэтому путь для установки гемов иногда меняют на vendor/bundle.

bundle config --local path vendor/bundle

Эта команда создаст файл .bundle/config, в котором будет указан путь установки. Bundler использует эту конфигурацию во время своей работы.

Интеграция в проект

Bundler появился намного позже чем RubyGems, поэтому он не включается автоматически. Для подключения Bundler, во входном файле нужно добавить сверху такой код:

require 'rubygems'
# Настраивает LOAD_PATH
require 'bundler/setup'

# Теперь можно подключать установленные гемы
require 'rails'

# Здесь код

В этом случае в пути загрузки добавятся все гемы из всех групп. Если нужно указать конкретные группы, то код меняется на такой:

require 'rubygems'
require 'bundler'
# Внутрь передается список групп
# :default - гемы вне групп
Bundler.setup(:default, :ci)

require 'nokogiri'

Когда гемов становится много, то постоянные включения зависимостей начинают сильно разрастаться. Bundler может взять эту работу на себя и включить все нужные зависимости сразу во время настройки:

require 'rubygems'
require 'bundler'
Bundler.require(:default, :test)

# Теперь гемы доступны напрямую из всех файлов проекта
# Этот способ подключения может замедлять старт приложения

В целом, прямая работа с подключением Bundler нужна редко. В прикладных проектах типа Rails, весь процесс инициализации скрыт от программиста. А для библиотек используется автоматическая генерация кода.


Дополнительные материалы

  1. Документация
  2. Выполнение команд из добавленных гемов (exec)
  3. bundle gem

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
Программирование на Ruby, Разработка веб-приложений и сервисов используя Rails, проектирование и реализация REST API
5 месяцев
c опытом
Старт 26 декабря

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»