名称: ruby-gems-bundler 用户可调用: false 描述: 用于处理Ruby gems、使用Bundler进行依赖管理、创建gemspecs,以及将gems发布到RubyGems。 允许的工具:
- Bash
- 读取
- 写入
- 编辑
Ruby Gems 和 Bundler
掌握Ruby的包管理系统,包括gems和Bundler。学习管理依赖、创建gems并发布到RubyGems。
Bundler 基础
Gemfile
source 'https://rubygems.org'
# Ruby 版本
ruby '3.3.0'
# 生产环境 gems
gem 'rails', '~> 7.1'
gem 'pg', '>= 1.1'
gem 'puma', '~> 6.0'
# 开发和测试环境 gems
group :development, :test do
gem 'rspec-rails'
gem 'factory_bot_rails'
gem 'faker'
end
# 仅开发环境
group :development do
gem 'rubocop'
gem 'rubocop-rails'
end
# 仅测试环境
group :test do
gem 'capybara'
gem 'selenium-webdriver'
end
# Git 源
gem 'my_gem', git: 'https://github.com/user/my_gem.git'
# 本地路径(用于开发)
gem 'local_gem', path: '../local_gem'
# 特定分支
gem 'experimental_gem', git: 'https://github.com/user/repo.git', branch: 'develop'
# 指定要求文件或false以不自动要求
gem 'sidekiq', require: 'sidekiq/web'
gem 'bootsnap', require: false
版本约束
# 精确版本
gem 'rails', '7.1.0'
# 悲观运算符(允许补丁更新)
gem 'rails', '~> 7.1.0' # >= 7.1.0 且 < 7.2.0
gem 'rails', '~> 7.1' # >= 7.1.0 且 < 8.0.0
# 大于或等于
gem 'pg', '>= 1.1'
# 范围
gem 'ruby-version', '>= 1.0', '< 2.0'
# 多个约束
gem 'nokogiri', '>= 1.10', '< 2.0'
Bundler 命令
# 从Gemfile安装所有gems
bundle install
# 安装到特定路径
bundle install --path vendor/bundle
# 更新所有gems
bundle update
# 更新特定gem
bundle update rails
# 检查过时的gems
bundle outdated
# 显示gem位置
bundle show rails
# 使用bundled gems执行命令
bundle exec rspec
# 在编辑器中打开gem
bundle open rails
# 检查Gemfile语法
bundle check
# 移除未使用的gems
bundle clean
# 列出所有已安装的gems
bundle list
# 显示依赖树
bundle viz
Gemfile.lock
Gemfile.lock 文件锁定gem版本以确保一致性安装:
# 始终将Gemfile.lock提交到版本控制
# 这确保所有开发者使用相同的gem版本
# 重新生成Gemfile.lock
rm Gemfile.lock
bundle install
创建 Gems
Gem 结构
# 创建新gem
bundle gem my_gem
# 结构:
my_gem/
├── lib/
│ ├── my_gem/
│ │ └── version.rb
│ └── my_gem.rb
├── spec/
│ ├── my_gem_spec.rb
│ └── spec_helper.rb
├── bin/
│ ├── console
│ └── setup
├── .gitignore
├── Gemfile
├── LICENSE.txt
├── my_gem.gemspec
├── Rakefile
└── README.md
Gemspec
# my_gem.gemspec
require_relative 'lib/my_gem/version'
Gem::Specification.new do |spec|
spec.name = "my_gem"
spec.version = MyGem::VERSION
spec.authors = ["您的名字"]
spec.email = ["您的邮箱@example.com"]
spec.summary = "gem的简短摘要"
spec.description = "gem功能的较长描述"
spec.homepage = "https://github.com/username/my_gem"
spec.license = "MIT"
spec.required_ruby_version = ">= 3.0.0"
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = "https://github.com/username/my_gem"
spec.metadata["changelog_uri"] = "https://github.com/username/my_gem/CHANGELOG.md"
# 指定应添加到gem的文件
spec.files = Dir.chdir(File.expand_path(__dir__)) do
`git ls-files -z`.split("\x0").reject do |f|
f.match(%r{\A(?:test|spec|features)/})
end
end
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
# 运行时依赖
spec.add_dependency "activesupport", "~> 7.0"
spec.add_dependency "nokogiri", ">= 1.10"
# 开发依赖
spec.add_development_dependency "rspec", "~> 3.12"
spec.add_development_dependency "rubocop", "~> 1.50"
end
版本文件
# lib/my_gem/version.rb
module MyGem
VERSION = "0.1.0"
end
主库文件
# lib/my_gem.rb
require_relative "my_gem/version"
require_relative "my_gem/core"
require_relative "my_gem/helpers"
module MyGem
class Error < StandardError; end
def self.configure
yield configuration
end
def self.configuration
@configuration ||= Configuration.new
end
class Configuration
attr_accessor :api_key, :timeout
def initialize
@api_key = nil
@timeout = 30
end
end
end
构建和发布
构建 Gem
# 本地构建gem
gem build my_gem.gemspec
# 这会创建 my_gem-0.1.0.gem
# 本地安装以测试
gem install ./my_gem-0.1.0.gem
# 卸载
gem uninstall my_gem
发布到 RubyGems
# 首次设置(一次性)
gem push my_gem-0.1.0.gem
# 您将被提示登录
# 后续推送
gem push my_gem-0.2.0.gem
# 撤回版本(从RubyGems移除)
gem yank my_gem -v 0.1.0
# 取消撤回版本
gem unyank my_gem -v 0.1.0
版本控制
# 语义版本控制:主版本.次版本.补丁版本
# 1.0.0 -> 1.0.1 (补丁)
# 1.0.1 -> 1.1.0 (次版本)
# 1.1.0 -> 2.0.0 (主版本)
# lib/my_gem/version.rb
module MyGem
VERSION = "1.0.0"
end
# 更新版本,然后构建和推送:
# 1. 编辑version.rb
# 2. gem build my_gem.gemspec
# 3. gem push my_gem-1.0.0.gem
RubyGems 命令
# 列出已安装的gems
gem list
# 搜索gems
gem search rails
# 显示gem信息
gem info rails
# 列出gem依赖
gem dependency rails
# 更新所有gems
gem update
# 更新特定gem
gem update rails
# 清理旧版本
gem cleanup
# 显示gem环境
gem env
# 安装特定版本
gem install rails -v 7.1.0
# 安装时不包含文档(更快)
gem install rails --no-document
# 卸载gem
gem uninstall rails
# 获取gem但不安装
gem fetch rails
Gem 分组
# 定义分组
group :development do
gem 'pry'
end
group :test do
gem 'rspec'
end
group :development, :test do
gem 'factory_bot'
end
# 安装时不包含特定分组
bundle install --without production
# 要求特定分组
Bundler.require(:default, :development)
Gem 源
# 主要源
source 'https://rubygems.org'
# 附加源
source 'https://gems.example.com' do
gem 'private_gem'
end
# Git 源
gem 'my_gem', git: 'https://github.com/user/my_gem.git'
gem 'my_gem', git: 'https://github.com/user/my_gem.git', tag: 'v1.0'
gem 'my_gem', git: 'https://github.com/user/my_gem.git', branch: 'main'
gem 'my_gem', git: 'https://github.com/user/my_gem.git', ref: 'abc123'
# GitHub 简写
gem 'my_gem', github: 'user/my_gem'
# 本地路径
gem 'my_gem', path: '../my_gem'
要求 Gems
# 在代码中
require 'my_gem'
# Bundler 根据Gemfile自动要求gems
# 禁用自动要求:
gem 'my_gem', require: false
# 然后在需要时手动要求:
require 'my_gem'
# 要求特定文件
gem 'sidekiq', require: 'sidekiq/web'
平台特定 Gems
# 仅安装在特定平台
gem 'pg', platforms: :ruby
gem 'sqlite3', platforms: [:mingw, :mswin, :x64_mingw]
# 多个平台
platforms :ruby do
gem 'pg'
gem 'nokogiri'
end
platforms :jruby do
gem 'activerecord-jdbc-adapter'
end
私有 Gems
使用私有 Gem 服务器
# Gemfile
source 'https://rubygems.org'
source 'https://gems.mycompany.com' do
gem 'private_gem'
end
使用 Git 凭证
# .netrc 文件用于私有仓库
machine github.com
login 您的用户名
password 您的令牌
Gem 开发
使用 bundle console
# 打开IRB并加载gem
bin/console
# 或
bundle console
运行测试
# 使用Rake
rake spec
# 或直接
bundle exec rspec
本地开发
# 在您的应用的Gemfile中,指向本地gem
gem 'my_gem', path: '../my_gem'
# 或使用bundle config
bundle config local.my_gem ../my_gem
最佳实践
- 始终将Gemfile.lock提交到版本控制
- 使用悲观版本控制(~>)以提高稳定性
- 保持gems更新但充分测试
- 使用分组来分离开发/测试/生产环境gems
- 在Gemfile中指定Ruby版本以确保一致性
- 使用bundle exec以确保正确的gem版本
- 记录gem依赖及其必要性
- 发布前在本地测试gems
- 遵循语义版本控制
- 保持gemspecs清晰且文档齐全
反模式
❌ 不要将vendor/bundle提交到git(使用.gitignore)
❌ 不要不必要地使用require: false——增加手动工作
❌ 除非绝对必要,不要指定精确版本
❌ 不要将未测试的gem版本推送到RubyGems
❌ 不要在gem包中包含不必要的文件
❌ 不要在gemspec或Gemfile中硬编码凭证
故障排除
# 清除bundler缓存
bundle clean --force
# 重新生成Gemfile.lock
rm Gemfile.lock && bundle install
# 检查gem冲突
bundle exec gem dependency
# 详细输出
bundle install --verbose
# 显示为何需要某个gem
bundle show rails
# 列出所有gem版本
bundle list
相关技能
- ruby-oop - 用于结构gem代码
- ruby-metaprogramming - 在许多gems中使用
- ruby-standard-library - 核心Ruby功能