首页
/ Rails 6.0 发布说明深度解读:Action Mailbox、Action Text 与多数据库时代的开启

Rails 6.0 发布说明深度解读:Action Mailbox、Action Text 与多数据库时代的开启

2026-09-06 09:04:20作者:魏献源Searcher

本文以 Rails 官方发布的 6.0 版本 Release Notes 为主体,系统梳理 Rails 6.0 的四大新特性(Action Mailbox、Action Text、Parallel Testing、Action Cable Testing)与九大组件(Railties、Action Cable、Action Pack、Action View、Action Mailer、Active Record、Active Storage、Active Model、Active Support、Active Job)的关键变更、移除项与弃用清单,并结合当前仓库中的实际源码(如 actionmailbox/lib/action_mailbox/router.rbactionmailer/lib/action_mailer/mail_delivery_job.rbactivesupport/lib/active_support/testing/parallelize_executor.rb 等)印证这些特性在框架中的落地实现,帮助你判断升级路径、识别废弃 API 的替代方案,并理解这些 6.0 引入的机制如何延续到当前主干。

说明:当前仓库处于 Rails 主干开发版本(见 RAILS_VERSION 所示的 8.2.0.alpha),而 6.0 Release Notes 是随仓库归档的历史版本文档。文中对源码的引用均基于当前仓库状态;凡属“当时引入”的内容,文中会注明来源为 Release Notes。

一、升级路径:先上 5.2,再看 6.0

Release Notes 对升级者给出的第一条建议很明确:不要跨版本直接升级。官方建议:

  • 进入升级前,先确保应用有足够好的测试覆盖;
  • 如果应用还停留在 5.1 或更早版本,先升级到 Rails 5.2,确认应用行为无变化后再向 6.0 迈进;
  • 升级时需要逐项核对的兼容性问题清单,在 Upgrading Ruby on Rails 指南的 "Upgrading from Rails 5.2 to Rails 6.0" 小节中。

6.0 的破坏性变化集中在三类:API 移除(5.x 中标记弃用的方法被正式删掉)、行为变更(如默认缓存存储、默认 JavaScript 编译器)和依赖版本下限提升(数据库版本、sqlite3 gem 版本)。后文按组件逐一列出。

二、四大新特性

2.1 Action Mailbox:把入站邮件路由给"邮箱"

Action Mailbox 是 Rails 6.0 最重磅的新增框架,它允许你将入站(incoming)邮件路由到类似 Controller 的 Mailbox 类中处理,与 ActionController 的路由哲学一脉相承。仓库中的实际代码结构印证了这一设计:

配套的入门文档即 6.0 同期新增的 Action Mailbox Basics 指南。

2.2 Action Text:富文本进入 Rails 应用

Action Text 为 Rails 带来富文本内容与编辑能力:

  • 内置 Trix 编辑器,支持格式化、链接、引用、列表、内嵌图片与图集;
  • 富文本内容保存为独立的 RichText 模型(见 actiontext/lib/action_text/richtext.rb),通过 has_rich_text 关联到任意已有的 Active Record 模型(如 PostMessage);
  • 富文本中嵌入的图片或其他附件自动经由 Active Storage 存储,并与所属 RichText 记录建立关联;
  • 数据库表结构由 actiontext/db/migrate 中的迁移文件创建,rich_texts 表保存经过处理的 HTML 内容。

详细用法参见 Action Text Overview

2.3 Parallel Testing:并行化测试套件

Parallel Testing 允许把整个测试套件拆分到多个进程中并行执行,显著缩短 CI 时间。Release Notes 指出:fork 进程是默认方式,同时也支持线程方式。当前仓库中的实现为:

典型用法(配合 CI 的并发数环境变量):

class ActiveSupport::TestCase
  # Rails 6.0 起,CI 环境会自动开启并行化
  parallelize(workers: :number_of_processors)
end

2.4 Action Cable Testing:连接、频道、广播全可测

Action Cable 的测试工具让 WebSocket 功能可以在任意层级被验证:连接(connection)、频道(channel)、广播(broadcast)。测试辅助代码位于 actioncable/lib/action_cable/test_helper.rb,测试用例基类在 actioncable/lib/action_cable/test_case.rb。典型场景:

class ChatChannelTest < ActionCable::Channel::TestCase
  setup { subscribe channel: "chat" }

  test "broadcasting" do
    broadcast_on "chat", message: "hi"
    assert_broadcast "chat", message: "hi"
  end
end

2.5 Action Cable 的其他变更

除了测试能力,Action Cable 在 6.0 还有几项值得关注的调整:

移除(Removals)

  • 移除 JS 端的 ActionCable.startDebugging() / ActionCable.stopDebugging(),改为设置 ActionCable.logger.enabled

值得注意的变更(Notable changes)

  • cable.yml 的 PostgreSQL 订阅适配器新增 channel_prefix 选项,便于区分不同环境的频道命名空间(实现见 subscription_adapter/postgresql.rbchannel_prefix 逻辑可在 actioncable/test/subscription_adapter/channel_prefix.rb 中找到测试依据);
  • 允许向 ActionCable::Server::Base 传入自定义配置;
  • 新增 :action_cable_connection:action_cable_channel 两个初始化 load hooks;
  • 新增 Channel::Base#broadcast_toChannel::Base.broadcasting_for(当前主干中的实现见 actioncable/lib/action_cable/channel/broadcasting.rbchannel/base.rb);
  • ActionCable::Connection 中调用 reject_unauthorized_connection 会直接关闭连接;
  • JS 包从 CoffeeScript 转为 ES2015,并在 npm 分发包中附带源码;
  • WebSocket adapter 与 logger adapter 的配置从 ActionCable 属性挪到 ActionCable.adapters 命名空间;
  • Redis 适配器新增 id 选项,用于区分 Action Cable 的多个 Redis 连接(对应 redis.rb)。

三、Railties:命令行与生成的现代化

移除项(Removals)

以下在 5.x 中已被弃用的能力在 6.0 中正式移除:

  • 插件模板中的 after_bundle 辅助方法;
  • config.ru 中以应用类作为 run 参数的旧写法;
  • rails 命令中弃用的 environment 参数;
  • 生成器与模板中的 capify! 方法;
  • config.secret_token(请迁移到 credentials/secret_key_base 体系)。

弃用项(Deprecations)

  • 以位置参数传 Rack 服务器名的 rails server 写法被弃用;
  • 使用 HOST 环境变量指定服务器 IP 的方式被弃用;
  • 以非 symbol 键访问 config_for 返回的 hash 被弃用。

值得注意的变更(Notable changes)

6.0 的 Railties 变更对日常开发体验影响最直接的有:

  • --using / -u 选项:为 rails server 指定 Rack 服务器(如 Puma)提供显式选项,取代被弃用的位置参数写法:bin/rails server --using puma
  • Webpacker 成为默认的 JavaScript 编译器rails new 生成的应用默认使用 Webpacker 处理 JS(当前主干已演进为 Importmaps/Propshaft 体系,见 guides/source/working_with_javascript_in_rails.md);
  • rails routes 支持展开格式:可以用长格式输出查看完整的路由匹配细节;
  • rails db:system:change:新增命令用于切换应用使用的数据库类型(当前主干中相关任务定义见 activerecord/lib/active_record/tasks/database_tasks.rb);
  • rails test:channels:新增命令用于只跑 Action Cable 频道测试;
  • DNS rebinding 防护:新增 ActionDispatch::HostAuthorization 中间件防止 DNS 重绑定攻击(当前主干实现见 actionpack/lib/action_dispatch/middleware/host_authorization.rb);
  • seed 任务改用 inline Active Job 适配器db:seed 在运行时以 perform_now 方式执行作业,避免依赖队列配置;
  • 生成器失败即中止:新增选项允许在生成器命令失败时终止后续步骤;
  • 多数据库支持扩展到命令层rails db:migrate:status 支持多数据库;生成器支持从多个数据库的不同迁移路径取迁移文件;
  • 多环境 credentialscredentials 机制支持按环境区分的密钥文件;
  • 测试环境默认 null_store 缓存:避免测试中被污染或依赖缓存状态。

四、Action Pack:请求管线的安全与语义加固

移除项

  • fragment_cache_key 辅助方法被移除,请使用 combined_fragment_cache_key
  • ActionDispatch::TestResponse 中的弃用方法被移除:#success?#successful?#missing?#not_found?#error?#server_error?

弃用项

值得注意的变更

6.0 在 Action Pack 上做了大量"语义收紧"与"安全加固",择要如下:

  • ActionDispatch::Response#content_type 原样返回 Content-Type 头(不再剥离参数);
  • 资源参数中出现冒号(:)时抛出 ArgumentError,避免隐晦的路由歧义;
  • ActionDispatch::SystemTestCase.driven_by 支持以 block 方式定义特定浏览器能力;
  • ActionDispatch::HostAuthorization 中间件:默认阻止对 localhost 的 DNS 重绑定攻击,是 6.0 的重要安全特性;
  • ActionController::TestCase 中允许使用 parsed_body
  • 同一上下文中出现多个无 as: 命名的 root 路由时抛出 ArgumentError
  • 允许用 #rescue_from 捕获参数解析错误(如 ActionController::InvalidJsonError);
  • ActionController::Parameters 新增 #each_value#each_key
  • send_data / send_file 对 Content-Disposition 中的文件名做 RFC 编码;
  • 签名/加密 cookie 内嵌 purpose 与过期元数据:防止把 A cookie 的值复制给 B cookie 后仍然通过验证;
  • 冲突的 respond_to 调用抛出 ActionController::RespondToMismatchError
  • 请求格式缺少模板时给出明确的错误页;
  • ActionDispatch::DebugExceptions.register_interceptor:在异常被渲染成调试页之前插入自定义拦截器;
  • 每个请求只输出一个 CSP nonce 头值;
  • 新增专门模块承载 Rails 默认响应头配置,可显式 include 进控制器;
  • ActionDispatch::Request::Session 新增 #dig

五、Action View、Action Mailer 与 Active Model

Action View

移除image_alt 辅助方法;空的 RecordTagHelper 模块(功能已迁至 record_tag_helper gem)。

弃用ActionView::Template.finalize_compiled_template_methods 及其配置项 config.action_view.finalize_compiled_template_methods(无替代,模板 finalizer 机制随 Zeitwerk 自动加载体系一并淡出);options_from_collection_for_select 中调用模型私有方法的做法。

值得注意的变更

  • 开发环境下只在模板文件变化时清空 Action View 缓存,显著提速开发模式;
  • 所有 Rails npm 包迁移到 @rails 命名空间(如 @rails/webpacker@rails/ujs);
  • 只接受已注册 MIME 类型的格式,拒绝未注册格式的隐式渲染;
  • 服务端模板/局部渲染输出中加入 allocations 统计;
  • date_select 新增 year_format 选项;
  • javascript_include_tag 新增 nonce: true 选项,自动为 CSP 生成 nonce;
  • rails_ujs 中把 confirm 调用抽成可覆写的独立方法;
  • 新增 config.action_controller.default_enforce_utf8(默认 false);
  • submit 标签支持 I18n key 风格的 locale 键。

Action Mailer

弃用

  • ActionMailer::Base.receive —— 入站邮件处理请迁移到 Action Mailbox
  • DeliveryJob / Parameterized::DeliveryJob —— 统一为 MailDeliveryJob

值得注意的变更

  • MailDeliveryJob 统一投递普通邮件与参数化邮件(当前实现见 actionmailer/lib/action_mailer/mail_delivery_job.rb);
  • 自定义邮件投递作业可与 Action Mailer 测试断言协同工作;
  • 多部分邮件用 block 定义时支持显式指定模板名;
  • deliver.action_mailer 通知 payload 中加入 perform_deliveries 字段,且关闭投递时日志明确提示"已跳过发送";
  • assert_enqueued_email_with 可无 block 调用;
  • assert_emails block 内的入队邮件作业会被实际执行;
  • ActionMailer::Base 支持反注册 observer 与 interceptor(unregister_observers / unregister_interceptors)。

Active Model

  • 新增配置项自定义 ActiveModel::Errors#full_message 的格式;
  • has_secure_password 支持自定义属性名;
  • ActiveModel::Errors 新增 #slice!#of_kind?
  • 修复 ActiveModel::Serializers::JSON#as_json 对时间戳的序列化;
  • 数值校验器在非 Active Record 场景继续使用类型转换前的值;
  • 修复 BigDecimalFloat 相等性数值校验(两端统一转为 BigDecimal);
  • 布尔属性对 :false/:"false" 等 falsy 符号正确转为 false
  • 多参数时间 hash 转换修复年份取值;ActiveModel::Type::Datevalue_from_multiparameter_assignment 返回正确日期;
  • 错误文案翻译先回退父 locale 再回退 :errors 命名空间。

六、Active Record:多数据库、批量写入与查询 API 扩展

移除项(节选)

  • 事务对象的 #set_state、适配器的 #supports_statement_cache?#insert_fixtures、SQLite3 适配器的 #valid_alter_table? 等弃用 API 被移除;
  • 移除"传 block 时向 sum/count 传列名"的支持
  • 移除 Relation 上缺失方法向 Arel 或类私有方法的 method_missing 委托;
  • 移除 #cache_key 指定时间戳列名的支持;
  • 移除 ActiveRecord::Migrator.migrations_path=expand_hash_conditions_for_aggregates

弃用项(节选)

  • 唯一性校验器对大小写不敏感排序规则的失配比较被弃用;
  • config.active_record.sqlite3.represent_boolean_as_integer 被弃用;
  • ActiveRecord::Result#to_hash → 请用 #to_a
  • DatabaseLimits 的一批方法(column_name_lengthtable_name_length 等)被弃用;
  • update_attributes / update_attributes! 被弃用,请改用 update / update!——这是影响面最广的一条。

值得注意的变更(按主题分组)

多数据库支持(6.0 的旗舰能力)

  • 连接切换 API(connected_to / with_connection 等),支持传入 hash 或 url 配置;
  • 自动切换数据库连接的能力;
  • 支持在 block 内禁止向某数据库写入;
  • rails db:schema:cache:dumpclear 支持多数据库;
  • ActiveRecord::Base.configurations 返回对象而非 hash,configurations= 接受 symbolize 后的 hash。

批量写入与条件操作

  • insert_all / insert_all! / upsert_all 批量插入(见 active_record/relation.rb);
  • #destroy_by / #delete_by 条件删除;
  • create_or_find_by / create_or_find_by!:借助数据库唯一约束解决 SELECT/INSERT 竞态(当前实现见 relation.rb);
  • replant 种子命令 rails db:seed:replant:truncate 各数据库当前环境的全部表并重载 seeds;
  • rails db:prepare:数据库不存在则创建,然后跑迁移。

查询 API

  • Relation#pick:单值 pluck 的简写(当前实现见 calculations.rb);
  • reselectunscope(:select).select(fields) 的简写;
  • Relation#extract_associated:从结果集中提取关联记录;
  • Relation#annotate:为 SQL 追加注释,便于在数据库端追踪来源;
  • 数据库 Optimizer Hints 支持;
  • where 支持 Ruby 2.6 的无界 Range(如 (1..));
  • 允许把 permitted 的 ActionController::Parameters 直接传给 #exists?

枚举与回调

  • enum 值为冻结常量,修改会报错;
  • 可为每个 enum 值生成"否定 scope"(如 not_active);
  • 支持禁用 ActiveRecord::Enum 生成的 scopes;
  • after_save_commit 回调,等价于 after_commit :hook, on: [:create, :update]

迁移与适配器

  • 迁移默认使用带精度(precision)的时间戳列;
  • create_table 支持 :if_not_existschange_table 支持 :index 选项;
  • 迁移中重复定义列时抛出异常;
  • 修复 reverted 迁移中 transaction 内命令未反向执行的 bug;
  • MySQL:默认 utf8mb4 字符集、ROW_FORMAT=DYNAMIC 默认建表选项、支持默认表达式与表达式索引、支持 :size 调整 text/blob 大小;
  • SQLite:支持表达式索引;alter_table 重建表后恢复外键;
  • PostgreSQL 最低版本 9.3;MySQL 最低版本 5.5.8;SQLite 最低版本 3.8;sqlite3 gem 最低 1.4。

其他

  • 多态关联 dependent: :nullify 同时把外键列与外键类型列置 NULL;
  • 关联 #size / #empty? 在有已加载记录时直接复用内存中的 ids;
  • 反序列化多态关联时可预加载"部分记录缺失"的关联;
  • StatementInvalid 的 SQL 与 binds 成为独立错误属性;
  • 支持在 #inspect 中过滤敏感字段;
  • 可配置禁用 advisory locks;
  • Relation#touch_allActiveRecord::Base.base_class?store_accessor 自定义前缀/后缀。

七、Active Storage:image_processing 时代开启

弃用

  • config.active_storage.queue → 拆分为 config.active_storage.queues.analysisconfig.active_storage.queues.purge,分析与清理可以跑在不同队列上;
  • ActiveStorage::DownloadingActiveStorage::Blob#open
  • 直接依赖 mini_magick 生成图片变体 → 统一走 image_processing gem(当前实现见 activestorage/lib/active_storage/variant.rbtransformer.rb);
  • ImageProcessing transformer 的 :combine_options(无替代)。

值得注意的变更

  • 支持 BMP、TIFF 变体,支持渐进式(progressive)JPEG 变体;
  • ActiveStorage.routes_prefix:自定义 Active Storage 生成的路由前缀;
  • 磁盘服务中文件缺失时,DiskController#show 返回 404;Blob#download / #open 抛出 ActiveStorage::FileNotFoundError
  • 新增统一基类 ActiveStorage::Error
  • 附件延迟落盘:分配给记录的上传文件在记录保存时才持久化到存储服务,而不是立即;
  • 集合赋值的替换语义config.active_storage.replace_on_assign_to_many 控制向多附件集合赋值时是整体替换还是追加;
  • 附件定义可被 Active Record 反射机制查看;
  • Blob#open:把 blob 下载到临时文件并 yield 该临时文件;
  • Google Cloud Storage 支持流式下载(要求 google-cloud-storage gem 1.11+)。

八、Active Support:并行测试、Hash#transform_values 家族与自动加载

移除项

  • Inflections#acronym_regex
  • Module#reachable?
  • Kernel#\``(反引号 exec,无替代,请直接用 Open3`/系统 API)。

弃用项

  • String#first / String#last 传负数参数;
  • ActiveSupport::Multibyte::Unicode#downcase/upcase/swapcase → 直接用 String 方法;
  • Multibyte::Unicode#normalize / Chars#normalizeString#unicode_normalize
  • Chars.consumes?String#is_utf8?
  • Unicode#pack_graphemes / unpack_graphemes → 用 array.flatten.pack("U*")string.scan(/\X/).map(&:codepoints)

值得注意的变更(节选)

测试与基础设施

  • 并行测试支持(即前文 Parallel Testing,见 parallelize_executor.rb);
  • 基于 Zeitwerk 的新自动加载机制成为 6.0 自动加载的地基,6.1 起成为默认(相关文档见 guides/source/autoloading_and_reloading_constants.md);
  • 支持通过日志追踪常量的 autoload;
  • Notifications.unsubscribe 正确处理正则或多模式订阅者;
  • Instrumenter#instrument 允许不传 block;
  • 使用弱引用维护 descendants tracker,允许匿名子类被 GC 回收;
  • 测试方法经 with_info_handler 调用,使 minitest-hooks 插件可用。

String / Hash / Array / Enumerable

  • String#truncate_bytes:按字节截断且不破坏多字节字符/字素簇;
  • String#strip_heredoc 保持字符串的 frozen 状态;
  • Hash#deep_transform_values / deep_transform_values!
  • HashWithIndifferentAccess 新增 #assoc#to_options 成为 #symbolize_keys 别名,修复 #without 对 symbol 参数的 bug;
  • Array#extract! / Enumerable#extract!:移除并返回满足条件的元素;
  • 新增 Array#including / Enumerable#includingwithout 更名为 excluding(旧名保留为别名);
  • Enumerable#index_with:从可枚举对象构造 hash;
  • Range#=== / cover? 支持以 Range 为参数;
  • transliterate / parameterize 支持传入 locale
  • safe_constantize 对大小写错误的常量不再抛 LoadError
  • delete_prefix / delete_suffix / unicode_normalize 视为非 HTML-safe 方法;SafeBuffer#* 保持 html_safe? 状态;HTML-safe 字符串切片后仍保持安全。

时间、缓存与日志

  • DateDateTimeTimeTimeWithZone 新增 before? / after?
  • unfreeze_time 作为 travel_back 别名;
  • 修复 Time#advance 在 1001-03-07 之前的日期失效的 bug;
  • ActiveSupport::Cache 启用压缩时存储膨胀的修复;
  • Redis 缓存 delete_matched 不再阻塞 Redis 服务器;increment/decrement 支持键过期;
  • Cache#fetch 新增 skip_nil 选项,不缓存 nil;
  • fetch_multi 保持传入键的顺序;
  • TimeZone.all 在个别时区数据缺失时不再整体失败;
  • TaggedLogging.new 返回新的 logger 实例,不再改动传入的 logger;
  • 通知事件携带 CPU 时间、空闲时间与内存分配量;
  • Module#parent 等重命名为 module_parent 系列,降低与业务代码的命名冲突。

九、Active Job:参数序列化与测试断言升级

移除:对 Qu gem 的支持。

值得注意的变更

  • 自定义参数序列化器:Active Job 参数支持可插拔的 serializer 机制;
  • 作业在入队时的时区中执行,避免跨时区部署的漂移;
  • retry_on / discard_on 支持一次传多个异常类;
  • enqueue / enqueue_at 的通知(notification)改由 around_enqueue 回调包裹,而非 after_enqueue
  • 重试与放弃(discard)周围新增回调钩子;
  • 测试辅助全面升级:assert_enqueued_withassert_enqueued_email_withperform_enqueued_jobsassert_performed_with 均可无 block 调用;断言新增 :queue 选项;支持对参数做子集匹配;断言辅助接受 Proc 作为 only;返回值中的参数为反序列化后的对象;比较时忽略时间值中的微秒/纳秒部分。

十、Guides 与文档

6.0 同期的指南更新包括:

结语:如何消费这份 Release Notes

  1. 升级核对:对照"移除项"检查你的代码是否还在调用已删除 API(如 update_attributesconfig.secret_tokenfragment_cache_key),这些会直接报错;
  2. 弃用迁移:对照"弃用项"安排迁移,例如把 mini_magick 直接依赖换成 image_processing、把 DeliveryJob 换成 MailDeliveryJob、把入站邮件逻辑迁入 Action Mailbox;
  3. 拥抱新能力:6.0 提供的多数据库连接切换、insert_all/upsert_allcreate_or_find_by、并行测试、CSP nonce 与 Host Authorization 安全加固,都是可以直接落地的能力;
  4. 深入细节:各组件的逐条变更请以对应 CHANGELOG 为准,仓库中分别位于 railties/CHANGELOG.mdactionpack/CHANGELOG.mdactionview/CHANGELOG.mdactionmailer/CHANGELOG.mdactioncable/CHANGELOG.mdactiverecord/CHANGELOG.mdactivestorage/CHANGELOG.mdactivemodel/CHANGELOG.mdactivesupport/CHANGELOG.mdactivejob/CHANGELOG.mdguides/CHANGELOG.md
登录后查看全文
热门项目推荐
相关项目推荐