Ruby on Rails 8.0 发布说明详解:Kamal 2、Thruster、Solid 系列、Propshaft 与 paramsexpect 全面解析
Rails 8.0 是 Ruby on Rails 生态的一个重要分水岭:它在默认栈中引入了 Kamal 2 部署方案、Thruster 前端代理、Solid Cable / Solid Cache / Solid Queue 数据库支撑组件、Propshaft 资产管道,以及开箱即用的认证系统生成器。本文基于仓库中的 8.0 发布说明 逐节展开,并结合 railties 应用生成器模板与 actionpack 源码,说明这些变更如何落到一个新建应用的具体文件、配置与代码中,帮助读者快速掌握 Rails 8.0 的能力边界与升级注意事项。
需要说明版本背景:当前仓库快照的版本号见 RAILS_VERSION(8.2.0.alpha),即本文引用的源码是 8.0 之后演进的代码,用于佐证发布说明中各项能力的实现;发布说明本身描述的是 8.0 引入的变更。
升级路径:先过 7.2,再看 8.0
发布说明给出的升级建议非常明确:
- 升级前保证应用有较好的测试覆盖;
- 如果还停留在 7.2 以下,先升级到 Rails 7.2 并确认应用行为正常;
- 8.0 升级时需要关注的破坏性变更清单,见 Upgrading Ruby on Rails 指南 中 "Upgrading from Rails 7.2 to Rails 8.0" 一节。
以下各节按发布说明的模块顺序展开。
重大特性(Major Features)
Kamal 2:部署成为 Rails 应用的一等公民
发布说明指出,Rails 现在预配置了 Kamal 2 用于部署:一条 kamal setup 命令即可把一台全新的 Linux 机器变成应用服务器或 accessory 服务器;Kamal 2 还自带了 Kamal Proxy 代理,取代了发布时的通用 Traefik 方案。
从仓库中的应用生成器模板可以验证这一点:
- 新建应用时,
kamalgem 默认写入 Gemfile(开发组),见 Gemfile 模板:
group :development do
# Deploy this application anywhere as a Docker container [https://kamal-deploy.org]
gem "kamal", require: false
end
-
同时生成
config/deploy.yml部署配置,见 deploy.yml 模板。其中关键配置项包括:service/image:应用名与容器镜像名;servers:web 服务器列表,以及注释示例中的 job 服务器(cmd: bin/jobs);registry:镜像仓库配置(localhost:5555为默认值,可换 Docker Hub、GHCR 等),密码类字段建议走.kamal/secrets;env.secret/env.clear:注入环境变量,Solid Queue 场景下默认开启SOLID_QUEUE_IN_PUMA: true(见下节);aliases:常用命令别名,如bin/kamal console、bin/kamal logs、bin/kamal dbc;volumes:为 SQLite 数据库文件与本地 Active Storage 文件挂载持久卷<app_name>_storage:/rails/storage;asset_path: /rails/public/assets:跨版本桥接指纹化资产,避免升级窗口期 404;builder.arch:镜像构建架构(默认 amd64,可配置远程构建机);- 注释示例中还有 accessory 服务(db、redis)、非 root SSH 用户等进阶项。
-
配套的
.kamal/secrets模板见 kamal-secrets 模板。
Thruster:Puma 前面的新代理
发布说明说明,Dockerfile 已升级以包含新的 Thruster 代理:它位于 Puma 前端,提供 X-Sendfile 加速、资产缓存与资产压缩。仓库中的实现证据:
- Gemfile 模板中默认加入该 gem,见 Gemfile 模板:
# Add HTTP asset caching/compression and X-Sendfile acceleration to Puma [https://github.com/basecamp/thruster/]
gem "thruster", require: false
- 生产 Dockerfile 的默认启动命令从直接跑
rails server变为经 Thruster 转发,见 Dockerfile 模板:
<% if skip_thruster? -%>
# Start the server by default, this can be overwritten at runtime
EXPOSE 3000
CMD ["./bin/rails", "server"]
<% else -%>
# Start server via Thruster by default, this can be overwritten at runtime
EXPOSE 80
CMD ["./bin/thrust", "./bin/rails", "server"]
<% end -%>
也就是说,默认生成的应用以 80 端口经 Thruster 暴露服务,bin/thrust 可执行文件模板见 thrust 模板;用 --skip-thruster 生成时则回退到 Puma 直接监听 3000 端口。
Solid Cable、Solid Cache、Solid Queue:用数据库替代 Redis/Memcached/Job 框架
发布说明中的三件套:
- Solid Cable:替代 Redis 作为 pubsub 服务器,负责在应用不同进程间转发 WebSocket 消息;默认在数据库中保留消息一天;
- Solid Cache:替代 Redis 或 Memcached,尤其用于 HTML 片段缓存;
- Solid Queue:替代 Redis + 独立任务框架(Resque、Delayed Job、Sidekiq 等)。高性能场景基于 PostgreSQL 9.5 首先引入的
FOR UPDATE SKIP LOCKED机制,MySQL 8.0 及以上同样可用,也支持 SQLite。
仓库中的落点:
- 这三个 gem 在新应用 Gemfile 中默认存在(可通过
--skip-solid跳过),见 Gemfile 模板:
<% unless options.skip_solid? -%>
# Use the database-backed adapters for Rails.cache, Active Job, and Action Cable
gem "solid_cache"
gem "solid_queue"
<% unless options.skip_action_cable? -%>
gem "solid_cable"
<% end -%>
<% end -%>
- Solid Queue 与 Puma 的集成写在生产 Puma 配置里,见 puma.rb 模板:
# Run the Solid Queue supervisor inside of Puma for single-server deployments.
plugin :solid_queue if ![ "", "false", "0" ].include?(ENV["SOLID_QUEUE_IN_PUMA"].to_s.downcase)
配合 deploy.yml 中的 SOLID_QUEUE_IN_PUMA: true,单机部署时 Supervisor 直接运行在 Puma 进程内;多机部署时则建议把任务处理拆到独立机器(deploy.yml 模板中有对应注释说明)。
Propshaft 成为默认资产管道
发布说明:Propshaft 取代 Sprockets 成为默认资产管道。这意味着新建 Rails 8.0 应用的默认资产处理不再走 Sprockets 的预编译与 require 语义,而是采用无构建、指纹化的方案;旧应用升级时需要处理 Sprockets 相关配置的迁移(见 Upgrading 指南)。
Authentication 系统生成器
发布说明:认证生成器为基于会话、可重置密码、带元数据跟踪的认证系统创建一个起点。从源码可以看清它到底生成了什么,见 authentication_generator.rb:
- 模型:
app/models/session.rb、app/models/user.rb、app/models/current.rb(Current Attributes 用法); - 控制器:
SessionsController、PasswordsController,以及注入ApplicationController的Authenticationconcern; - 邮件:
app/mailers/passwords_mailer.rb及 HTML/TEXT 重置邮件视图; - 路由:
resources :passwords, param: :token与resource :session; - 依赖:自动
bundle add bcrypt(Gemfile 中已有则启用); - 迁移:
users表(email_address:string!:uniq password_digest:string!)与sessions表(user:references ip_address:string user_agent:string)——后两个字段正是"元数据跟踪"的落地:会话记录登录来源 IP 与 User-Agent; - 支持
--api选项:只生成 API 风格控制器与模型,不带视图模板。
对应的模板文件位于 authentication 模板目录,例如 sessions_controller.rb 模板 与 Authentication concern 模板。
各框架变更详解
Railties
移除(Removals)
- 移除已弃用的
config.read_encrypted_secrets; - 移除已弃用的文件
rails/console/app; - 移除已弃用的文件
rails/console/helpers; - 移除通过
Rails::ConsoleMethods扩展 Rails 控制台的已弃用支持。
弃用(Deprecations)
- 弃用
require "rails/console/methods"; - 弃用直接修改
STATS_DIRECTORIES,改用Rails::CodeStatistics.register_directory。新 API 在 code_statistics.rb 中有完整用法示例:
# Rails::CodeStatistics.register_directory("My Directory", "path/to/dir")
# Rails::CodeStatistics.register_directory("Model specs", "spec/models", test_directory: true)
def self.register_directory(label, path, test_directory: false)
- 弃用
bin/rake stats,改用bin/rails stats。
值得注意的变更
- 默认将
Regexp.timeout设为 1 秒,以应对正则拒绝服务(ReDoS)攻击。实现位于应用启动配置中,见 configuration.rb:
Regexp.timeout ||= 1 if Regexp.respond_to?(:timeout=)
注意 ||= 语义:如果应用自己已经设置过该值,框架不会覆盖。
更细的 Railties 变更见 railties/CHANGELOG.md。
Action Pack
移除
- 移除
Rails.application.config.action_controller.allow_deprecated_parameters_hash_equality配置。
弃用
- 弃用为同一路由绘制多个路径(drawing routes with multiple paths),以加快路由构建。
值得注意的变更:params#expect
发布说明引入了更安全、更显式的参数处理方法 params#expect:params.expect(table: [ :attr ]) 可以替代 params.require(:table).permit(:attr) 两步写法。源码实现见 strong_parameters.rb:
def expect(*filters)
params = permit_filters(filters)
keys = filters.flatten.flat_map { |f| f.is_a?(Hash) ? f.keys : f }
values = params.require(keys)
values.size == 1 ? values.first : values
end
实现要点:expect 先对过滤条件做 permit_filters,再对展开的 key 做 require(缺失时按原有行为抛出 ActionController::ParameterMissing,默认渲染 400 响应)。此外还配套了 expect!:
def expect!(*filters)
expect(*filters)
rescue ParameterMissing => e
raise ExpectedParameterMissing.new(e.param, e.keys)
end
expect! 抛出的 ExpectedParameterMissing 是未被默认 rescue 处理的异常,适用于内部 API 调试场景——参数格式错误说明客户端库存在 bug,应当直接暴露而不是渲染 400。文档示例(同文件注释,L764-L777)表明支持嵌套哈希与标量数组:
params = ActionController::Parameters.new(person: { name: "Francesco", age: 22, pets: [...] })
permitted = params.expect(person: [ :name, { pets: [[:name]] } ])
ActionController::Parameters.new(tags: ["rails", "parameters"]).expect(tags: [])
# => ["rails", "parameters"](一个已许可的 Array)
更多 Action Pack 变更见 actionpack/CHANGELOG.md。
Action View
移除
- 移除向
form_with的model:参数传nil的已弃用支持; - 移除在
tagbuilder 上向 void 标签元素(如tag.br)传内容的已弃用支持。
Action Mailer
8.0 中 Action Mailer 无重大移除、弃用或显著变更(发布说明对应小节为空)。详见 actionmailer/CHANGELOG.md。
Active Record
移除(共 9 项)
- 移除已弃用的
config.active_record.commit_transaction_on_non_local_return; - 移除已弃用的
config.active_record.allow_deprecated_singular_associations_name; - 移除查找未向 Active Record 注册的数据库适配器的已弃用支持;
- 移除以关键字参数定义
enum的已弃用支持; - 移除已弃用的
config.active_record.warn_on_records_fetched_greater_than; - 移除已弃用的
config.active_record.sqlite3_deprecated_warning; - 移除已弃用的
ActiveRecord::ConnectionAdapters::ConnectionPool#connection; - 移除向
cache_dump_filename传数据库名的已弃用支持; - 移除通过设置
ENV["SCHEMA_CACHE"]控制 schema cache 的已弃用支持。
弃用
SQLite3Adapter的retries选项被弃用,改用timeout。
值得注意的变更:全新数据库上 db:migrate 的行为
在全新数据库上运行 db:migrate 现在会先加载 schema 文件,再运行待执行的迁移;后续调用则只运行未完成的迁移。如果确实需要旧的"从零跑迁移"行为,应运行 db:migrate:reset——它会先 drop 并重建数据库,再执行迁移。
Active Storage
弃用
- 弃用 Active Storage 的 Azure 后端。
详见 activestorage/CHANGELOG.md。
Active Model
8.0 无重大移除、弃用或显著变更。详见 activemodel/CHANGELOG.md。
Active Support
移除
- 移除已弃用的
ActiveSupport::ProxyObject; - 移除在
attr_internal_naming_format中使用@前缀的已弃用支持; - 移除向
ActiveSupport::Deprecation#warn传字符串数组的已弃用支持。
弃用
- 弃用
Benchmark.ms; - 弃用两个
Time之间、以及Time与ActiveSupport::TimeWithZone之间的加法与since运算。
详见 activesupport/CHANGELOG.md。
Active Job
移除
- 移除已弃用的
config.active_job.use_big_decimal_serializer。
弃用
- 弃用
enqueue_after_transaction_commit; - 弃用内置的
SuckerPunch适配器,改用sucker_punchgem 自带的适配器。
Action Cable / Action Text / Action Mailbox
发布说明中这三个模块在 8.0 的 Removals / Deprecations / Notable changes 小节均为空,即无重大变更。分别参考 actioncable/CHANGELOG.md、actiontext/CHANGELOG.md、actionmailbox/CHANGELOG.md。
升级检查清单(汇总)
基于以上发布说明与仓库源码,从 7.2 升级到 8.0 时的关键核对项:
- 控制台与加密密钥:确认代码中不再依赖
config.read_encrypted_secrets、rails/console/app、rails/console/helpers、Rails::ConsoleMethods或require "rails/console/methods"; - 代码统计:把对
STATS_DIRECTORIES的修改迁移到Rails::CodeStatistics.register_directory(见 code_statistics.rb),并把bin/rake stats换成bin/rails stats; - Strong Parameters:
allow_deprecated_parameters_hash_eality相关配置已不存在,代码中若有依赖需清理;可借机把require(...).permit(...)改写为params#expect; - Action View:
form_with(model: nil)与向 void 标签传内容的写法必须移除; - Active Record:清理 9 项已移除配置与 API;SQLite 适配器的
retries换成timeout;重新评估迁移流程——全新库上db:migrate语义已变,必要时用db:migrate:reset; - Active Storage:Azure 后端被弃用,需要迁移到其他服务或版本锁定;
- Active Support / Active Job:移除/替换
ProxyObject、Benchmark.ms、跨 Time 类型的+/since、use_big_decimal_serializer、enqueue_after_transaction_commit、内置 SuckerPunch 适配器; - 安全默认值:
Regexp.timeout默认 1 秒(configuration.rb),长耗时正则可能触发自带超时,注意评估; - 部署与运行栈:新建应用默认携带 Kamal 2、Thruster、Solid 三件套与 Propshaft,升级旧应用时可视情况分阶段引入。
完整的 bug 修复与细节变更以各框架 CHANGELOG 为准(上文已给出对应相对路径),发布说明本身只覆盖重大变更。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0626
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00