依赖管理 #

Bundler 概述 #

Bundler 是 Ruby 项目的依赖管理工具,它提供了完整的依赖解析、版本锁定和环境隔离功能。

为什么使用 Bundler? #

bash
# 没有 Bundler 的问题
# 项目 A 需要 rails 6.0
# 项目 B 需要 rails 7.0
# 全局安装会冲突

# 使用 Bundler
# 每个项目独立的依赖环境
bundle install --path vendor/bundle

依赖解析 #

解析机制 #

Bundler 使用依赖解析算法来确定要安装的 Gem 版本:

text
1. 读取 Gemfile 中的依赖声明
2. 获取所有可用版本
3. 解析依赖关系图
4. 选择满足所有约束的版本组合
5. 写入 Gemfile.lock

解析过程示例 #

ruby
# Gemfile
gem 'rails', '~> 7.0'
gem 'sidekiq', '~> 7.0'

# 解析过程
# 1. rails ~> 7.0 需要 actionpack ~> 7.0
# 2. actionpack ~> 7.0 需要 activesupport ~> 7.0
# 3. sidekiq ~> 7.0 需要 redis ~> 5.0
# 4. 选择满足所有约束的版本

版本选择策略 #

ruby
# 悲观约束 (~>)
gem 'rails', '~> 7.0.0'  # 7.0.x,不升级到 7.1
gem 'rails', '~> 7.0'    # 7.x,不升级到 8.0

# 范围约束
gem 'rails', '>= 7.0', '< 8.0'

# 精确版本
gem 'rails', '7.0.4'

安装依赖 #

基本安装 #

bash
# 安装所有依赖
bundle install

# 安装到项目目录
bundle install --path vendor/bundle

# 安装到系统目录
bundle install --system

# 安装时跳过生产依赖
bundle install --without production

# 安装特定分组
bundle install --with development test

安装选项 #

选项 描述
--path 指定安装目录
--system 安装到系统目录
--without 排除分组
--with 包含分组
--jobs 并行安装数
--retry 重试次数
--deployment 部署模式
--clean 清理旧版本
--full-index 使用完整索引

部署模式 #

bash
# 部署模式安装(生产环境推荐)
bundle install --deployment

# 等同于
bundle install --path vendor/bundle --without development test --clean

并行安装 #

bash
# 使用 4 个并行任务
bundle install --jobs 4

# 自动检测 CPU 核心数
bundle install --jobs $(nproc)

更新依赖 #

更新策略 #

bash
# 更新所有依赖
bundle update

# 更新特定 Gem
bundle update rails

# 更新多个 Gem
bundle update rails sidekiq

# 只更新 patch 版本
bundle update --patch

# 只更新 minor 版本
bundle update --minor

# 只更新 major 版本
bundle update --major

保守更新 #

bash
# 保守更新(优先使用已安装版本)
bundle update --conservative

# 严格更新(严格遵循版本约束)
bundle update --strict

更新 Bundler 本身 #

bash
# 更新 Bundler
bundle update --bundler

# 更新到特定版本
bundle update --bundler 2.4.0

版本锁定 #

Gemfile.lock 的作用 #

text
1. 记录精确的版本号
2. 记录依赖树结构
3. 记录下载源
4. 记录平台信息
5. 确保团队一致性

Gemfile.lock 结构 #

text
GEM
  remote: https://rubygems.org/
  specs:
    actionpack (7.0.4)
      actionview (= 7.0.4)
      activesupport (= 7.0.4)
    rails (7.0.4)
      actionpack (= 7.0.4)

GIT
  remote: https://github.com/rails/rails.git
  revision: abc123
  specs:
    rails (7.1.0.alpha)

PATH
  remote: ../my_gem
  specs:
    my_gem (1.0.0)

PLATFORMS
  ruby
  x86_64-linux

DEPENDENCIES
  rails (~> 7.0)
  my_gem!

BUNDLED WITH
   2.4.0

锁定文件管理 #

bash
# 检查是否最新
bundle check

# 查看依赖树
bundle show

# 查看特定 Gem
bundle show rails

# 查看依赖路径
bundle show rails --paths

依赖隔离 #

项目级隔离 #

bash
# 安装到项目目录
bundle install --path vendor/bundle

# 目录结构
project/
├── vendor/
│   └── bundle/
│       └── ruby/
│           └── 3.2.0/
│               ├── gems/
│               └── specifications/
├── Gemfile
└── Gemfile.lock

使用 bundle exec #

bash
# 在 Bundle 环境中运行
bundle exec ruby app.rb
bundle exec rails server
bundle exec rspec

# 不使用 bundle exec 可能的问题
# 使用系统安装的 Gem 版本
# 可能与项目依赖不一致

binstubs #

bash
# 生成 binstubs
bundle binstubs rails

# 使用 binstubs
bin/rails server
bin/rspec

# 添加到 PATH
export PATH="./bin:$PATH"

分组管理 #

定义分组 #

ruby
# Gemfile
group :development do
  gem 'pry'
  gem 'rubocop'
end

group :test do
  gem 'rspec'
  gem 'factory_bot'
end

group :development, :test do
  gem 'pry-byebug'
end

group :production do
  gem 'puma'
  gem 'sentry-ruby'
end

安装特定分组 #

bash
# 排除分组
bundle install --without development test

# 包含分组
bundle install --with development

# 多个分组
bundle install --without development test production

运行时分组 #

ruby
# 在代码中加载特定分组
Bundler.require(:default, :development)

# 条件加载
Bundler.require(:default, Rails.env)

平台管理 #

平台特定依赖 #

ruby
# 指定平台
gem 'tzinfo-data', platform: :windows

# 多个平台
gem 'ffi', platform: [:mingw, :x64_mingw]

# 平台块
platforms :ruby do
  gem 'pg'
end

platforms :jruby do
  gem 'activerecord-jdbcpostgresql-adapter'
end

平台类型 #

平台 描述
:ruby C Ruby (MRI), Rubinius
:mri C Ruby (MRI)
:jruby JRuby
:truffleruby TruffleRuby
:windows Windows
:linux Linux
:mac macOS

安装时平台检查 #

bash
# 查看当前平台
bundle platform

# 显示详细平台信息
bundle platform --ruby

依赖检查 #

检查依赖状态 #

bash
# 检查依赖是否满足
bundle check

# 检查并显示缺失
bundle check --dry-run

查看过时依赖 #

bash
# 检查过时的 Gem
bundle outdated

# 只检查特定 Gem
bundle outdated rails

# 只检查 patch 更新
bundle outdated --patch

# 只检查 minor 更新
bundle outdated --minor

# 只检查 major 更新
bundle outdated --major

查看依赖树 #

bash
# 显示依赖树
bundle show

# 显示详细依赖
bundle show --verbose

# 生成依赖图
bundle viz

# 生成 PNG 图片
bundle viz --format=png

查看依赖关系 #

bash
# 查看 Gem 信息
bundle info rails

# 查看 Gem 路径
bundle info rails --path

# 查看 Gem 版本
bundle info rails --version

清理依赖 #

清理未使用的 Gem #

bash
# 清理未使用的 Gem
bundle clean

# 强制清理
bundle clean --force

# 干运行
bundle clean --dry-run

清理旧版本 #

bash
# 清理旧版本 Gem
gem cleanup

# 清理特定 Gem
gem cleanup rails

# 干运行
gem cleanup --dryrun

依赖问题排查 #

依赖冲突 #

bash
# 查看依赖树
bundle viz

# 查看特定 Gem 依赖
gem dependency rails

# 强制解析
bundle update --conservative

版本不兼容 #

bash
# 查看可用版本
gem search rails --all

# 安装特定版本
bundle update rails -v 7.0.4

# 强制更新
bundle update rails --force

网络问题 #

bash
# 使用镜像源
bundle config set mirror.https://rubygems.org https://gems.ruby-china.com

# 使用代理
bundle config set proxy http://proxy.example.com:8080

# 增加超时
bundle install --retry 5

高级配置 #

Bundler 配置 #

bash
# 查看配置
bundle config

# 设置配置
bundle config set path 'vendor/bundle'

# 设置全局配置
bundle config set --global path 'vendor/bundle'

# 设置本地配置
bundle config set --local path 'vendor/bundle'

# 删除配置
bundle config unset path

配置文件 #

yaml
# .bundle/config
---
BUNDLE_PATH: "vendor/bundle"
BUNDLE_JOBS: "4"
BUNDLE_RETRY: "3"
BUNDLE_WITHOUT: "development:test"

常用配置 #

bash
# 设置安装路径
bundle config set path 'vendor/bundle'

# 设置并行数
bundle config set jobs 4

# 设置重试次数
bundle config set retry 3

# 排除分组
bundle config set without 'development test'

# 设置镜像源
bundle config set mirror.https://rubygems.org https://gems.ruby-china.com

# 设置部署模式
bundle config set deployment true

# 设置清理模式
bundle config set clean true

CI/CD 集成 #

GitHub Actions #

yaml
name: CI

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: '3.2'
          bundler-cache: true
          
      - name: Install dependencies
        run: bundle install --jobs 4 --retry 3
        
      - name: Run tests
        run: bundle exec rspec
        
      - name: Run linter
        run: bundle exec rubocop

GitLab CI #

yaml
test:
  image: ruby:3.2
  
  cache:
    paths:
      - vendor/bundle
      
  before_script:
    - bundle install --path vendor/bundle --jobs 4 --retry 3
    
  script:
    - bundle exec rspec
    - bundle exec rubocop

CircleCI #

yaml
version: 2.1

jobs:
  test:
    docker:
      - image: cimg/ruby:3.2
        
    steps:
      - checkout
      
      - restore_cache:
          keys:
            - bundle-v1-{{ checksum "Gemfile.lock" }}
            
      - run:
          name: Install dependencies
          command: bundle install --path vendor/bundle
          
      - save_cache:
          key: bundle-v1-{{ checksum "Gemfile.lock" }}
          paths:
            - vendor/bundle
            
      - run:
          name: Run tests
          command: bundle exec rspec

最佳实践 #

版本约束 #

ruby
# 推荐:允许 minor 更新
gem 'rails', '~> 7.0'

# 不推荐:无约束
gem 'rails'

# 不推荐:过于严格
gem 'rails', '7.0.4.1'

分组策略 #

ruby
# 清晰的分组
group :development, :test do
  gem 'pry'
  gem 'rspec'
end

group :production do
  gem 'puma'
end

锁定文件管理 #

bash
# 始终提交 Gemfile.lock
git add Gemfile.lock

# 定期更新依赖
bundle update

# 安全更新
bundle update --patch

依赖审计 #

bash
# 安装审计工具
gem install bundler-audit

# 检查安全漏洞
bundle audit

# 更新漏洞数据库
bundle audit update

下一步 #

现在你已经掌握了 Bundler 的依赖管理功能,接下来学习 创建 Gem 开发自己的 RubyGem!

最后更新:2026-03-28