首页
/ Rails 7.0 发布说明深度解读:升级路径与各框架关键行为变更全解析

Rails 7.0 发布说明深度解读:升级路径与各框架关键行为变更全解析

2026-09-06 12:08:34作者:苗圣禹Peter

本篇基于 Rails 官方的 7.0 发布说明(guides/source/7_0_release_notes.md)展开,系统梳理升级到 Rails 7.0 的前置条件、Sprockets 依赖解耦、Active Record 事务与查询合并的行为变更、button_to 的 HTTP 动词推断等核心特性,并结合仓库源码印证各变更的实际落地方式,帮助你在从 6.1 升级到 7.0(乃至更晚版本)时准确预判破坏性改动。需要说明的是,当前仓库主干版本为 8.2.0.alpha(见 RAILS_VERSION),本文内容适用于理解 7.0 这一里程碑的变更脉络及其在后续版本中的演进。

升级前置条件:Ruby 版本要求与升级路径

Rails 7.0 对运行环境提出了明确的版本底线:

  • 必须 Ruby 2.7.0+;
  • 推荐 Ruby 3.0+。

官方对存量应用升级给出了两步走建议:

  1. 先确保应用有良好的测试覆盖率——没有回归网兜底的情况下直接跨大版本升级风险很高;
  2. 先升级到 Rails 6.1,确认应用行为符合预期后,再升级到 7.0。

升级时需要逐项对照的破坏性改动清单,收录在 Upgrading Ruby on Rails 指南的 “From Rails 6.1 to Rails 7.0” 章节中,与本文各节的框架级变更互为补充。

Railties:Sprockets 成为可选依赖

这是 Rails 7.0 中最具实操影响的一项变更:rails gem 不再依赖 sprockets-rails。Sprockets 从框架的默认配置中解耦出来,成为可选依赖。

如果你的应用仍在使用 Sprockets 管理静态资源,必须在 Gemfile 中显式声明:

gem "sprockets-rails"

这一变更的背景是 Rails 官方正在向 Propshaft 等更轻量的资产方案迁移,将资产管道从核心依赖中剥离可以让不需要 Sprockets 的应用少装一层依赖。升级检查时,凡是没有显式声明该 gem 且仍依赖 app/assets 目录下 Sprockets 逻辑的应用,都会在新版本中报缺失依赖错误。

另外,Railties 在 7.0 中还移除了 dbconsole 中已弃用的 config 用法(见 railties/CHANGELOG.md 的对应条目)。

Action Pack:集中清理 6.x 时代的弃用 API

Action Pack 在 7.0 中的变更以“移除弃用项”为主,共 4 项,主要涉及路由与测试工具:

  • 移除弃用的 ActionDispatch::Response.return_only_media_type_on_content_type
  • 移除弃用的 Rails.config.action_dispatch.hosts_response_app(该配置在 7.0 之前已被默认开启的 config.hosts 机制取代);
  • 移除弃用的 ActionDispatch::SystemTestCase#host!
  • 移除 fixture_file_upload 中允许传入相对 fixture_path 路径的弃用支持。

前两项的移除意味着:如果你的应用还在旧版配置中设置 hosts_response_app,或依赖 return_only_media_type_on_content_type 的旧行为,升级后将直接报错而非警告。系统测试中 host! 的移除则要求改为通过 driven_by 或浏览器实例管理 host。

Action View:button_to 自动推断 HTTP 动词

这是 7.0 中对前端行为可见性影响最大的一项变更:button_to 使用 Active Record 对象构建 URL 时,HTTP 动词会自动从路由推断。此前 button_to 一律默认 post,升级后按钮实际发出的请求方法可能改变:

button_to("Do a POST", [:do_post_action, Workshop.find(1)])
# 升级前
#=> <input type="hidden" name="_method" value="post" autocomplete="off" />
# 升级后(路由声明的动词是 patch 时)
#=> <input type="hidden" name="_method" value="patch" autocomplete="off" />

这个行为在当前源码中可以清晰看到:navigation_helper.rbbutton_to 的核心逻辑是——

method = (html_options.delete("method").presence || method_for_options(options)).to_s

即:优先采用显式传入的 method 选项,否则回退到 method_for_options(options) 依据路由信息推断。因此推断只在“未显式指定 method 且 URL 由路由+对象构建”时发生。升级时的自查方法:搜索所有未传 method: 选项、且 action 路由并非 postbutton_to 调用,确认控制器端的 wrap_parameters 与 CSRF 校验逻辑与新动词兼容。

Action Mailer:统一为 MailDeliveryJob

7.0 移除了已弃用的 ActionMailer::DeliveryJobActionMailer::Parameterized::DeliveryJob,统一收敛为 ActionMailer::MailDeliveryJob。在当前仓库中,该类定义于 mail_delivery_job.rb,其 perform 签名同时承载了参数化投递与普通投递两种路径:

class MailDeliveryJob < ActiveJob::Base
  def perform(mailer, mail_method, delivery_method, args:, kwargs: nil, params: nil)

params: 参数正是从 Parameterized::DeliveryJob 合并而来的痕迹。升级时需要注意:

  • 队列名称从 ActionMailer::DeliveryJob / ActionMailer::Parameterized::DeliveryJob 变为 ActionMailer::MonitorJob 之外的单一 ActionMailer::MailDeliveryJob旧队列名残留的任务不会自动被消费,升级窗口内需要手动处理已入队的旧任务;
  • 任何硬编码旧 Job 类名的监控、重试逻辑都要同步更新。

Active Record:事务回滚、条件合并与 PostgreSQL interval 变更

Active Record 是 7.0 变更最密集的框架,按重要程度分述如下。

1. 事务块提前返回时回滚而非提交

7.0 之前,事务块中提前 return(以及更隐蔽的超时中断)会走 commit 路径,导致不完整的事务被提交。7.0 起,块提前返回时事务改为回滚。这一变更的动机在原文档中有明确说明:超时机制曾在事务块内部触发中断,旧行为会把残缺事务提交进数据库。从源码结构看,该逻辑落在 transaction 实现的收尾分支中(参见 activerecord/CHANGELOG.md 中 “Rollback transactions when the block returns earlier than expected” 条目)。对业务的影响:所有依赖“提前 return 也算提交”的隐式约定的代码(比如用 return 代替 raise 的事务保护)需要在升级前显式改为 return 前手动回滚或抛出异常。

2. 同列条件合并:rewhere 语义转正

merge 时同列条件冲突的处理在 6.1 是过渡状态(IN 子句被替换、范围条件双方共存),7.0 统一为:后者(被合并侧)条件一致性地替换前者rewhere: true 选项成为唯一迁移手段:

# Rails 6.1:IN 子句被替换
Author.where(id: [david.id, mary.id]).merge(Author.where(id: bob)) # => [bob]
# Rails 6.1:范围条件双方共存(已弃用行为)
Author.where(id: david.id..mary.id).merge(Author.where(id: bob)) # => []
# 用 rewhere 提前对齐 7.0 行为
Author.where(id: david.id..mary.id).merge(Author.where(id: bob), rewhere: true) # => [bob]
# Rails 7.0:两种写法行为一致,均被替换
Author.where(id: [david.id, mary.id]).merge(Author.where(id: bob)) # => [bob]
Author.where(id: david.id..mary.id).merge(Author.where(id: bob)) # => [bob]

实操建议:在 6.1 阶段全局搜索 .merge( 并对涉及条件覆盖的调用补上 rewhere: true,跑一遍测试即可确认对齐 7.0 语义。

3. PostgreSQL interval 列返回 ActiveSupport::Duration

7.0 移除了 :interval 列返回字符串的弃用警告,interval 列从此直接返回 ActiveSupport::Duration 对象。若业务必须保留旧的字符串行为,可以在模型中显式声明列类型:

attribute :column, :string

4. 大规模移除弃用 API(升级自查清单)

7.0 一次性移除了自 Rails 4.x~6.x 积累的弃用面,主要包括:

  • 连接与配置:connected_todatabase 关键字参数、"primary" 连接规格名、DatabaseConfig#configActiveRecord::Base.connection_configconfigurations.default_hash / configurations.to_hDatabaseConfig#spec_name
  • SQL 安全:ActiveRecord::Base.allow_unsafe_raw_sql(7.0 起不安全 SQL 直接抛错,不再提供开关)、ActiveRecord::Base.arel_attributetype_cast 传入列名的支持、对 ActiveRecord::Base 对象执行 quote/type-cast 的支持;
  • 序列化:移除以 Rails 4.1/4.2 YAML 格式加载 ActiveRecord::Base 实例的支持;
  • 查询:Model.reorder(nil).first 借助非确定性排序检索的弃用支持;
  • 任务 API:Tasks::DatabaseTasks 下的 schema_filedump_filenamecurrent_configspec、带 environment/name 参数的 schema_up_to_date? 等,以及一批 db:structure:*db:test:load_structure*db:schema:load_if_ruby 等弃用 rake 任务;
  • 连接与结果对象:ActiveRecord::Connection#allowed_index_name_length#in_clause_lengthActiveRecord::Result#map! / #collect!ActiveRecord::Base#remove_connection

其中 Tasks::DatabaseTasks.schema_file_type 则在 7.0 中被新弃用(后续版本移除)。这类清理的共性是:7.0 是 Rails 6 系列弃用债务的“总清账”,升级前建议用 Rails::Deprecation 日志扫一遍 6.1 下的全量弃用告警。

Active Model:Errors 彻底告别 Hash 接口

7.0 移除了把 ActiveModel::Errors 当 Hash 使用的全部旧接口:to_hslice!valueskeysto_xml,以及通过 #messages 拼接(concat)、cleardelete[]= 修改错误的隐式支持。同时移除了对 Rails 5.x 错误格式的 Marshal/YAML 反序列化支持,以及 5.x 格式 ActiveModel::AttributeSet 的 Marshal 支持。

影响面提示:所有形如 errors.to_h 序列化进 JSON/缓存、或从旧版本遗留的序列化错误数据反序列化的代码路径都会失效,需要迁移到 errors.details / errors.attribute_names 等现代接口。

Active Support:to_s 传 format 弃用,让位给 to_fs

这是 7.0 中影响面最广的弃用项:对 ArrayRangeDateDateTimeTimeBigDecimalFloatInteger 调用带 format 参数的 #to_s 被弃用,应改用 #to_fs

弃用的动机是承接 Ruby 3.1 对字符串插值的底层优化——不再覆盖这些类的 to_s 后,"#{obj}" 走 Ruby 原生的更快路径。对应开关:

  • 新应用:默认不覆盖上述类的 to_s
  • 存量应用:通过 config.active_support.disable_to_s_conversion 显式关闭覆盖以获取性能收益(注意:该配置在 Rails 7.1 被弃用、7.2 移除,属于过渡性开关)。

另外 7.0 还移除了 4 项弃用:config.active_support.use_sha1_digestsURI.parserRange#include? 用于日期时间范围成员判断的旧行为、ActiveSupport::Multibyte::Unicode.default_normalization_form

Active Job:回调中断语义定型

7.0 定型了回调链的中断语义:当 after_enqueue / after_perform 回调链中前一个回调通过 throw :abort 中断时,后续回调不再执行——旧版本“中断后仍继续执行”的行为被移除。同时移除了 :return_false_on_aborted_enqueue 配置选项。

值得注意的过渡点:Rails.config.active_job.skip_after_callbacks_if_terminated 在 7.0 中被弃用(后续版本移除)。当前仓库的 callbacks.rbdefine_callbacks 仍保留 skip_after_callbacks_if_terminated 关键字参数,说明该参数已从“用户可配置的开关”退化为回调注册层的内部机制——这也是它在配置层面被弃用的原因。

Action Mailbox:移除 Mailgun 旧凭据通道

7.0 移除了两项 Mailgun 接入的弃用通道:

  • Rails.application.credentials.action_mailbox.mailgun_api_key
  • 环境变量 MAILGUN_INGRESS_API_KEY

Mailgun ingress 的凭据管理统一收敛到 ingress 专用的 credentials 体系(见 actionmailboxconfig/initializers 相关文档与 CHANGELOG)。升级时若应用依赖上述旧配置项,需在部署前迁移凭据来源,否则 Mailgun 回调验签将直接失败。

各框架 Changelog 对照索引

发布说明中每个框架都指向其详细 Changelog,在当前仓库中对应的文件如下,升级与回归验证时可逐项核对:

框架 Changelog 路径
Railties railties/CHANGELOG.md
Action Pack actionpack/CHANGELOG.md
Action View actionview/CHANGELOG.md
Action Mailer actionmailer/CHANGELOG.md
Action Cable actioncable/CHANGELOG.md
Active Record activerecord/CHANGELOG.md
Active Storage activestorage/CHANGELOG.md
Active Model activemodel/CHANGELOG.md
Active Support activesupport/CHANGELOG.md
Active Job activejob/CHANGELOG.md
Action Text actiontext/CHANGELOG.md
Action Mailbox actionmailbox/CHANGELOG.md
Guides guides/CHANGELOG.md

升级 7.0 的落地检查清单

综合以上变更,一份可执行的升级清单如下:

  1. 环境:Ruby 升至 2.7+(推荐 3.0+);
  2. 资产管道:仍在用 Sprockets 的应用在 Gemfile 中显式添加 gem "sprockets-rails"
  3. 先升 6.1 并开启弃用日志,收集全量 deprecation 告警,对照本文各框架 Removals 清单逐项清零;
  4. Active Record:审查事务块中的提前 return 路径;为条件覆盖场景补 rewhere: true;PostgreSQL interval 列确认 Duration 类型影响;
  5. Active Job:确认 MailDeliveryJob 队列迁移方案,清理旧队列名;
  6. Active Support:批量替换带 format 的 to_sto_fs,评估 disable_to_s_conversion 开关(仅 7.0 生效);
  7. 视图层:排查 button_to 动词推断带来的请求方法变化;
  8. Action Mailbox:迁移 Mailgun 凭据配置。

Rails 7.0 的整体定位是一次“清账式”版本:新增特性克制,重点是清除 4.x 以来积累的弃用债务并固化 6.1 的过渡行为。理解上述每一项变更的“旧行为 → 新行为”映射,配合各框架 Changelog 的条目级核对,即可把跨大版本升级的风险控制在可回滚范围内。

登录后查看全文
热门项目推荐
相关项目推荐