关于 rails-upgrade
rails-upgrade 是用于评估 Rails 应用升级的 skill,检查版本差异、官方升级指南、配置变化和 JavaScript 依赖。它强调先识别本地修改,再制定选择性合并计划,避免直接覆盖定制文件。
主要功能
- 01核验 Rails 应用与当前版本
- 02比较最新版本及升级类型
- 03汇总升级指南和文件差异
- 04检查 Rails 相关 JavaScript 依赖
- 05按本地修改制定选择性合并
适用场景
- 01评估 Rails 版本升级复杂度
- 02查找升级所需的配置与迁移
- 03在升级时保留项目定制内容
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ robzolkos/ skill-rails-upgrade --skill rails-upgrade安装后在 Claude Code 中输入/rails-upgrade确认已加载。
附带文件README.md
详细介绍
Rails 升级分析器
分析当前的 Rails 应用,并提供全面的升级评估,同时选择性合并文件。
步骤 1:验证 Rails 应用
检查当前目录是否为 Rails 应用,确认以下文件是否存在:
Gemfile(必须存在且包含“rails”)config/application.rb(Rails 应用配置)config/environment.rb(Rails 环境)
如果缺少其中任何文件,或这些文件表明当前目录并非 Rails 应用,请停止并告知用户:这似乎不是 Rails 应用。
步骤 2:获取当前 Rails 版本
按以下顺序提取当前 Rails 版本:
- 首先,检查
Gemfile.lock中精确的已安装版本(查找rails (x.y.z)) - 如果未找到,则检查
Gemfile中的版本约束
报告当前的精确版本(例如,7.1.3)。
步骤 3:查找最新 Rails 版本
使用 GitHub CLI 获取最新的 Rails 版本:
gh api repos/rails/rails/releases/latest --jq '.tag_name'
这会返回最新的稳定版本标签(例如,v8.0.1)。比较版本时去掉“v”前缀。
同时检查近期标签,了解版本发布情况:
gh api repos/rails/rails/tags --jq '.[0:10] | .[].name'
步骤 4:确定升级类型
比较当前版本和最新版本,并对升级进行分类:
- 补丁升级:主版本号和次版本号相同,补丁版本号不同(例如,7.1.3 → 7.1.5)
- 次版本升级:主版本号相同,次版本号不同(例如,7.1.3 → 7.2.0)
- 主版本升级:主版本号不同(例如,7.1.3 → 8.0.0)
步骤 5:获取升级指南
使用 WebFetch 获取官方 Rails 升级指南:
URL:https://guides.rubyonrails.org/upgrading_ruby_on_rails.html
查找与版本升级相关的章节。该指南按目标版本组织,包含以下类型的章节:
- “从 Rails X.Y 升级到 Rails X.Z”
- 破坏性变更
- 弃用警告
- 配置变更
- 必需的迁移
提取并总结与用户特定升级路径相关的章节。
步骤 6:获取 Rails 差异
使用 WebFetch 从 railsdiff.org 获取版本间的差异:
URL:https://railsdiff.org/{current_version}/{target_version}
例如:https://railsdiff.org/7.1.3/8.0.0
其中展示了:
- 默认配置文件的变更
- 需要添加的新文件
- 已修改的初始化文件
- 已更新的依赖项
bin/脚本的变更
总结主要文件变更。
步骤 7:检查 JavaScript 依赖项
Rails 应用通常包含需要随 Rails 一起更新的 JavaScript 包。检查并报告这些依赖项。
7.1:识别 JS 包管理器
检查应用使用的包管理器:
# Check for package.json (npm/yarn)
ls package.json 2>/dev/null
# Check for importmap (Rails 7+)
ls config/importmap.rb 2>/dev/null
7.2:检查与 Rails 相关的 JS 包
如果存在 package.json,请检查以下与 Rails 相关的包:
# Extract current versions of Rails-related packages
cat package.json | grep -E '"@hotwired/|"@rails/|"stimulus"|"turbo-rails"' || echo "No Rails JS packages found"
要检查的主要包:
| 包 | 用途 | 版本对应关系 |
|---|---|---|
@hotwired/turbo-rails | Turbo Drive/Frames/Streams | 应与 Rails 的版本时期相匹配 |
@hotwired/stimulus | Stimulus JS 框架 | 通常在不同 Rails 版本间保持稳定 |
@rails/actioncable | WebSocket 支持 | 应与 Rails 版本相匹配 |
@rails/activestorage | 直接上传 | 应与 Rails 版本相匹配 |
@rails/actiontext | 富文本编辑 | 应与 Rails 版本相匹配 |
@rails/request.js | Rails UJS 的替代方案 | 应与 Rails 的版本时期相匹配 |
7.3:检查更新
对于 npm/yarn 项目,检查是否有可用更新:
# Using npm
npm outdated @hotwired/turbo-rails @hotwired/stimulus @rails/actioncable @rails/activestorage 2>/dev/null
# Or check latest versions directly
npm view @hotwired/turbo-rails version 2>/dev/null
npm view @rails/actioncable version 2>/dev/null
7.4:检查 Importmap Pins(如适用)
如果应用使用 importmap-rails,请检查 config/importmap.rb 中固定的版本:
cat config/importmap.rb | grep -E 'pin.*turbo|pin.*stimulus|pin.*@rails' || echo "No importmap pins found"
要更新 importmap 固定项:
bin/importmap pin @hotwired/turbo-rails
bin/importmap pin @hotwired/stimulus
7.5:JS 依赖项摘要
在升级摘要中加入:
### JavaScript Dependencies
**Package Manager**: [npm/yarn/importmap/none]
| Package | Current | Latest | Action |
|---------|---------|--------|--------|
| @hotwired/turbo-rails | 8.0.4 | 8.0.12 | Update recommended |
| @rails/actioncable | 7.1.0 | 8.0.0 | Update with Rails |
| ... | ... | ... | ... |
**Recommended JS Updates:**
- Run `npm update @hotwired/turbo-rails` (or yarn equivalent)
- Run `npm update @rails/actioncable @rails/activestorage` to match Rails version
步骤 8:生成升级摘要
提供全面的摘要,包含步骤 1-7 的所有发现:
版本信息
- 当前版本:X.Y.Z
- 最新版本:A.B.C
- 升级类型:[补丁/次版本/主版本]
升级复杂度评估
根据以下因素,将升级评定为小型、中型或大型:
| 因素 | 小型 | 中型 | 大型 |
|---|---|---|---|
| 版本跨度 | 仅补丁版本 | 次要版本 | 主要版本 |
| 破坏性变更 | 无 | 少量,且有详尽文档 | 许多,影响重大 |
| 配置变更 | 极少 | 适中 | 大量 |
| 弃用项 | 无待处理项 | 有一些需要处理 | 许多,需要重构 |
| 依赖项 | 兼容 | 需要更新一些 | 需要更新主要依赖项 |
需要处理的关键变更
列出用户需要处理的最重要变更:
- 配置文件更新
- 需要更新的弃用方法/功能
- 新增的必需依赖项
- 需要的数据库迁移
- 破坏性 API 变更
建议的升级步骤
- 更新测试套件并确保测试通过
- 检查当前版本中的弃用警告
- 使用新的 Rails 版本更新 Gemfile
- 运行
bundle update rails - 更新 JavaScript 依赖项(参见 JS Dependencies 部分)
- 不要直接运行
rails app:update——请使用下文的选择性合并流程 - 运行数据库迁移
- 运行测试套件
- 检查并更新弃用代码
资源
- Rails 升级指南:https://guides.rubyonrails.org/upgrading_ruby_on_rails.html
- Rails Diff:https://railsdiff.org/{current}/{target}
- 发布说明:https://github.com/rails/rails/releases/tag/v{target}
第 9 步:选择性更新文件(替代 rails app:update)
**重要:**不要运行 rails app:update,因为它会覆盖文件而不考虑本地自定义内容。请改为遵循以下选择性合并流程:
9.1:检测本地自定义内容
开始升级前,先找出包含本地自定义内容的文件:
# Check for uncommitted changes
git status
# List config files that differ from a fresh Rails app
# These are the files we need to be careful with
git diff HEAD --name-only -- config/ bin/ public/
在以下类别中,列出相关文件:
- 自定义配置文件:包含项目特定设置的文件(i18n、mailer 等)
- 已修改的 bin 脚本:包含自定义行为的脚本(例如使用 foreman 的 bin/dev)
- 标准文件:未经过自定义的文件
9.2:分析 railsdiff 中的必要变更
根据第 6 步中 railsdiff 的输出,对每个发生变更的文件进行分类:
| 类别 | 操作 | 示例 |
|---|---|---|
| 新文件 | 直接创建 | config/initializers/new_framework_defaults_X_Y.rb |
| 本地未修改 | 可安全覆盖 | public/404.html(如果未自定义) |
| 本地已自定义 | 需要手动合并 | config/application.rb、bin/dev |
| 仅注释变更 | 通常跳过 | 配置文件中的少量注释更新 |
9.3:制定升级计划
向用户提供清晰的升级计划:
## Upgrade Plan: Rails X.Y.Z → A.B.C
### New Files (will be created):
- config/initializers/new_framework_defaults_A_B.rb
- bin/ci (new CI script)
### Safe to Update (no local customizations):
- public/400.html
- public/404.html
- public/500.html
### Needs Manual Merge (local customizations detected):
- config/application.rb
└─ Local: i18n configuration
└─ Rails: [describe new Rails changes if any]
- config/environments/development.rb
└─ Local: letter_opener mailer config
└─ Rails: [describe new Rails changes]
- bin/dev
└─ Local: foreman + Procfile.dev setup
└─ Rails: changed to simple ruby script
### Skip (comment-only or irrelevant changes):
- config/puma.rb (only comment changes)
9.4:执行升级计划
用户确认计划后:
对于新文件:
直接使用 railsdiff 中的内容创建,或从全新的 Rails 应用中提取:
# Generate a temporary fresh Rails app to extract new files
cd /tmp && rails new rails_template --skip-git --skip-bundle
# Then copy needed files
也可以使用 Rails 生成器创建特定文件:
bin/rails app:update:configs # Only updates config files, still interactive
对于可安全更新的文件:
覆盖这些文件,因为它们没有本地自定义内容。
对于需要手动合并的文件:
对于每个需要合并的文件,向用户展示:
- 当前本地版本(用户的自定义内容)
- 新的 Rails 默认版本(来自 railsdiff)
- 建议的合并版本,该版本:
- 保留所有本地自定义内容
- 仅添加必要的新 Rails 功能
- 移除已弃用的设置
config/application.rb 的合并示例:
# KEEP local customizations:
config.i18n.available_locales = [:de, :en]
config.i18n.default_locale = :de
config.i18n.fallbacks = [:en]
# ADD new Rails 8.1 settings if needed:
# (usually none required - new defaults come via new_framework_defaults file)
9.5:处理 Active Storage 迁移
更新文件后,运行任何新的迁移:
bin/rails db:migrate
检查是否添加了新的迁移:
ls -la db/migrate/ | tail -10
9.6:验证升级
完成合并后:
-
启动 Rails 服务并检查错误:
bin/dev # or bin/rails server -
检查 Rails 控制台:
bin/rails console -
运行测试套件:
bin/rails test -
检查日志中的弃用警告
步骤 10:完成框架默认设置
确认应用正常运行后:
- 检查
config/initializers/new_framework_defaults_X_Y.rb - 逐一启用每项新默认设置,并在每次启用后进行测试
- 启用并测试所有默认设置后,更新
config/application.rb:config.load_defaults X.Y # Update to new version - 删除
new_framework_defaults_X_Y.rb文件
错误处理
- 如果
ghCLI 未通过身份验证,请指示用户运行gh auth login - 如果 railsdiff.org 没有确切版本,请尝试使用 major.minor.0 版本
- 如果应用已经是最新版本,请祝贺用户,并告知即将发布的版本
- 如果本地自定义内容会丢失,务必先停止,并在继续之前向用户展示哪些内容会被覆盖
关键原则
- 未经检查,绝不覆盖——始终先检查本地自定义内容
- 尊重用户意图——本地自定义内容都有其存在的理由
- 尽量减少改动——只添加新 Rails 版本所必需的内容
- 保持透明——准确告知用户将进行哪些更改
- 可逆性——如有需要,用户应能通过
git checkout恢复