首页
/ Rails 4.0 发布说明:Strong Parameters、Russian Doll 缓存与 Turbolinks 如何重塑现代 Rails

Rails 4.0 发布说明:Strong Parameters、Russian Doll 缓存与 Turbolinks 如何重塑现代 Rails

2026-09-06 12:18:35作者:冯爽妲Honey

本文基于 Rails 官方指南 4.0 Release Notes,完整梳理 Ruby on Rails 4.0 版本的核心特性、框架级变更与各组件弃用清单,并结合当前仓库源码(如 strong_parameters.rbcache_helper.rb)印证这些特性在当代 Rails 中的落地形态,帮助读者理解版本升级路径与安全、缓存两大关键机制的设计动机。

Rails 4.0 核心特性图

版本定位与升级前提

Rails 4.0 发布于 2012 年,其发布说明开篇即给出四条主线变化:

  • Ruby 2.0 为推荐版本,最低要求 1.9.3+;
  • Strong Parameters(强参数)取代 ActiveModel 批量赋值保护;
  • Turbolinks 提升前端导航体验;
  • Russian Doll Caching(俄罗斯套娃缓存)取代页面/动作缓存。

对于存量应用的升级,官方建议的路径是:

  1. 先确保应用具备良好的测试覆盖;
  2. 若尚未升级,先升到 Rails 3.2 并验证应用行为符合预期;
  3. 再尝试升级到 Rails 4.0,逐条对照 Upgrading Ruby on Rails 指南中“从 Rails 3.2 升级到 4.0”章节列出的注意事项。

需要特别说明适用前提:当前仓库处于 8.2.0.alpha 开发线(见 RAILS_VERSION),本篇所述均为 4.0 版本的历史特性。文中涉及的每一项特性,都可以在当前仓库源码中找到其后代实现,可作为验证线索。

创建 Rails 4.0 应用

前提是安装好 rails RubyGem,基础流程为:

# You should have the 'rails' RubyGem installed
$ rails new myapp
$ cd myapp

使用 Gemfile 管理依赖

Rails 4.0 起,应用根目录的 Gemfile 成为确定应用所需依赖的唯一入口:由 Bundler 处理该文件、安装全部依赖,并支持将依赖安装到应用本地目录,使应用不再依赖系统全局 gem。

使用边缘版本(Living on the Edge)

借助 Bundler 与 Gemfile,冻结 Rails 应用的部署变得容易:

# 直接从 Git 仓库 bundle Rails
$ rails new myapp --edge

如果本地已有 Rails 仓库检出,并希望基于它生成应用,使用 --dev 标志:

$ ruby /path/to/rails/railties/bin/rails new myapp --dev

框架级变更:从核心中移除的功能

Rails 4.0 对框架做了显著“瘦身”,一批功能被移出核心:

被移除/提取的功能 移除原因(原文说明)
Ruby 1.9.3 要求(commit a0380e8) Ruby 2.0 推荐,1.9.3+ 必需
新的弃用政策 4.0 中废弃功能仅给出警告,4.1 中移除
ActionPack 页面缓存与动作缓存(commit b0a7068) 需要过多手动干预(底层模型更新时需手动失效缓存),改用 Russian doll caching
ActiveRecord Observers(commit ccecab3) 仅服务于页面/动作缓存,且易产生面条式代码
ActiveRecord Session Store(commit 0ffe190) 把 session 存进 SQL 代价高,建议改用 cookie session、memcache session 或自定义 store
ActiveModel 批量赋值保护(commit f8c9a4d) 被 Strong Parameters 取代
ActiveResource(commit f1637bf) 使用面不广,提取为独立 gem
vendor/plugins 目录(commit 853de2b) 统一用 Gemfile 管理 gem

ActionPack 核心新特性

Strong Parameters:只允许被许可的参数更新模型

Rails 3 的批量赋值保护(attr_accessible 等)被废弃,替代方案是在控制器中显式声明哪些参数可以进入模型:

# 只允许 title 与 text 两个参数更新模型对象
params.permit(:title, :text)

在当前仓库中,该机制的主体实现位于 ActionController::Parameters,其 permit 方法(L675)根据过滤器列表构造一个新的“已许可”参数对象,未许可的参数默认被记录警告(可通过 ActionController::Parameters.action_on_unpermitted_parameters 配置为 :raise 等策略)。从源码注释看,当代版本进一步提供了更严格的 expect 方法,用于同时完成“要求 + 许可”,并规避 .require(:user).permit(...) 链式调用在参数类型被篡改时的类型陷阱——这正是 4.0 引入该机制时“显式白名单”思路的延续与强化。

配套的模型侧防护是 ActiveModel::ForbiddenAttributesProtection,当收到未许可参数时保护属性不被批量赋值(见下文 Active Model 章节)。

Routing Concerns:路由 DSL 提取公共子路由

路由 DSL 支持把公共子路由抽取成 concern。例如 /posts/1/comments/videos/1/comments 中的 comments 子路由只需定义一次,即可分别挂到 post 与 video 下。当前仓库的路由映射器 mapper.rb 中仍保留 :concerns 作为资源选项之一(RESOURCE_OPTIONS),resource/resources 方法也接受 concerns: 关键字参数,印证了该特性一脉相承。

ActionController::Live:流式 JSON 输出

通过 response.stream 可将 JSON 以流式方式写回客户端,适用于需要增量推送的长响应场景,无需等待整个响应体构建完成。

Declarative ETags:声明式 ETag

在控制器层面声明额外的 etag 计算项,这些项会并入当前 action 的 etag 计算,使条件请求(304)的粒度更精细、声明更集中。

Russian Doll Caching:嵌套片段缓存

4.0 缓存策略的核心变化:不再缓存整页/整动作,而是缓存视图的嵌套片段。每个片段基于一组依赖(cache key)过期;cache key 通常由模板版本号与模型对象共同组成。父片段失效时,内部嵌套片段随之失效,形似俄罗斯套娃。

在当前仓库中,该机制的入口是 CacheHelpercache 块:

<% cache project do %>
  <b>All the topics on this project</b>
  <%= render project.topics %>
<% end %>

源码注释给出的缓存键形如 views/模板路径/模板树摘要/类名/id,并与记录的 cache version 结合——当 projectupdated_at 被 touch,#cache_version 变化,即使稳定键不变,缓存也会自动过期,从而避免传统 key-based expiration 产生大量“垃圾键”。模板本身的 MD5 摘要则保证修改模板文件也能自动失效缓存。模型侧的 cache_key 实现在 Relation#cache_keyActiveRecord::Integration 中,cache_key_with_versionrelation.rb#L533)则对应上述“键稳定、版本变化”的失效机制。

Turbolinks:只传输必要内容

Turbolinks 的工作方式是:首屏正常返回一个完整的 HTML 页面;用户点击站内链接时,使用 pushState 更新浏览器地址栏,再用 AJAX 获取下一页,仅更新页面标题与 <body> 内容。配合 Rails 端的 csrf-tokendata-turbolinks-track 等约定,可在不整页刷新的前提下保持服务端渲染体验。

依赖解耦

  • ActionView 与 ActionController 解耦:ActionView 从 ActionPack 中分离,规划在 Rails 4.1 移入独立 gem。事实上当前仓库中 ActionView 已是独立框架目录 actionview
  • ActionPack 不再依赖 ActiveModel,进一步降低框架内部耦合。

General:通用能力变更

  • ActiveModel::Model(commit 3b822e9):混入模块,让普通 Ruby 对象开箱即用地与 ActionPack 协作(例如供 form_for 使用)。当前仓库中对应文件为 activemodel/lib/active_model/model.rb
  • 新 scope API(commit 50cbc03):scopes 必须使用 callable(Proc/Lambda);
  • Schema cache dump(commit 5ca4fc9):为改善启动时间,schema 不再直接查询数据库,而是从一个 dump 文件加载;
  • 事务隔离级别可指定(commit 392eeec):允许在“可重复读”与“更少的锁、更好的性能”之间按库选择;
  • Dalli(commit 8266330):memcache store 改用 Dalli 客户端,替代已废弃的 memcache-client gem;
  • 通知的 start 与 finish(commit f08f875):Active Support instrumentation 向订阅者报告事件的开始与结束两个时间点;
  • 默认线程安全(commit 5d416b9):Rails 无需额外配置即可在多线程应用服务器中运行。注意:需自行检查所依赖的 gem 是否线程安全;
  • PATCH 取代 PUT(commit eed9f25):PATCH 用于资源的部分更新,成为标准动词。

安全变更

4.0 在安全上是该版本最重要的主线之一:

  1. match 不再默认捕获所有动词(commit 90d2802):路由 DSL 中 match 必须显式指定 HTTP 动词,避免意外暴露写操作端点;
  2. HTML 实体默认转义(commit 5f189f4):在 ERB 中渲染的字符串默认转义,除非显式包裹 raw 或调用 html_safe,从根本上防御 XSS;
  3. 新增安全响应头(commit 6794e92):每个 HTTP 响应附带以下头:
    • X-Frame-Options:禁止页面被嵌入 frame,防点击劫持;
    • X-XSS-Protection:提示浏览器中止脚本注入;
    • X-Content-Type-Options:防止浏览器把 jpeg 按 exe 打开(防 MIME 嗅探)。

提取到独立 Gem 的功能清单

以下功能从 4.0 核心中移出,如需使用,直接将其加入 Gemfile 即可恢复对应能力:

  • 基于 Hash 与动态查找器方法:activerecord-deprecated_finders
  • Active Record 模型的批量赋值保护:protected_attributes
  • ActiveRecord::SessionStoreactiverecord-session_store
  • Active Record Observers:rails-observers
  • Active Resource:activeresource
  • Action Caching:actionpack-action_caching
  • Page Caching:actionpack-page_caching
  • Sprockets:sprockets-rails
  • 性能测试:rails-perftest

各框架组件变更明细

Railties

  • 新增测试目录约定:test/modelstest/helperstest/controllerstest/mailers,并配套新增对应的 rake task;
  • 应用的可执行文件移至 bin/ 目录,运行 rake rails:update:bin 可生成 bin/bundlebin/railsbin/rake
  • Threadsafe 默认开启;
  • rails new--builder-b)自定义 builder 选项被移除,建议改用 application templates。

弃用项:

  • config.threadsafe! 被弃用,推荐 config.eager_load 以更细粒度地控制 eager load 行为;
  • Rails::Plugin 彻底移除:不再使用 vendor/plugins,改用 gem 或 Bundler 的 path/git 依赖。

Action Mailer

4.0 的 Action Mailer 无突出变更记录,详情参见其 CHANGELOG

Active Model

  • 新增 ActiveModel::ForbiddenAttributesProtection:一个简单的模块,当传入未许可属性时保护模型属性不被批量赋值——与 Strong Parameters 配套的另一半防线;
  • 新增 ActiveModel::Model:让 Ruby 对象开箱即用地与 Action Pack 协作。

Active Support

突出变更:

  • ActiveSupport::Cache::MemCacheStoredalli 替代已废弃的 memcache-client

  • ActiveSupport::Cache::Entry 优化,降低内存与处理开销;

  • 变词规则(inflections)可按 locale 定义,singularizepluralize 接受 locale 作为附加参数;

  • Object#try 在对象未实现该方法时返回 nil 而非抛 NoMethodError;旧行为可用新的 Object#try! 获得;

  • String#to_date 遇到非法日期时抛出 ArgumentError: invalid date,与 Date.parse 行为一致,接受的“无效日期”范围比 3.x 更宽:

    # ActiveSupport 3.x
    "asdf".to_date # => NoMethodError: undefined method `div' for nil:NilClass
    "333".to_date # => NoMethodError: undefined method `div' for nil:NilClass
    
    # ActiveSupport 4
    "asdf".to_date # => ArgumentError: invalid date
    "333".to_date # => Fri, 29 Nov 2013
    

弃用项:

  • ActiveSupport::TestCase#pending,改用 minitest 的 skip
  • ActiveSupport::Benchmarkable#silence 因线程不安全被弃用,4.1 中无替代地移除;
  • ActiveSupport::JSON::Variable:自定义 JSON 字面量请自行实现 #as_json#encode_json
  • 兼容方法 Module#local_constant_names,改用返回 Symbol 的 Module#local_constants
  • ActiveSupport::BufferedLogger,改用 ActiveSupport::Logger 或 Ruby 标准库 logger;
  • assert_presentassert_blank,改用 assert object.blank?assert object.present?

Action Pack

  • 开发模式异常页面样式改版,且所有异常页面额外显示触发异常的代码行与代码片段;
  • 无其他突出弃用项。

Active Record

突出变更:

  • change 迁移改进,多数场景不再需要编写 up/down

    • drop_tableremove_column 变得可逆(前提是提供了足够信息);remove_column 不再接受多个列名,改用不可逆的 remove_columnschange_table 只要块内不调用 removechangechange_default 即可自动逆推;
    • 新增 reversible 方法,允许显式指定 up/down 各方向执行的代码;
    • 新增 revert 方法,可回滚整个先前迁移或指定代码块——down 迁移时,给定迁移/块按原样执行。

    上述 reversiblerevert 的用法在当前仓库的 active_record_migrations.md 指南中有完整说明;

  • 新增 PostgreSQL 数组类型支持:任意数据类型都可创建数组列,具备完整的迁移与 schema dumper 支持;

  • 新增 Relation#load:显式加载记录并返回 self

  • Model.all 现在返回 ActiveRecord::Relation 而非记录数组;确需数组时调用 Relation#to_a。升级时个别场景可能因此出现行为变化;

  • 新增 ActiveRecord::Migration.check_pending!:存在未执行的迁移时抛错;

  • ActiveRecord::Store 支持自定义 coder:

    store :settings, accessors: [ :color, :homepage ], coder: JSON
    
  • mysql/mysql2 连接默认设置 SQL_MODE=STRICT_ALL_TABLES,避免静默数据丢失;可在 database.yml 中指定 strict: false 关闭;

  • 移除 IdentityMap;

  • 移除 EXPLAIN 自动执行:active_record.auto_explain_threshold_in_seconds 配置项不再使用,应从配置中删除;

  • 新增 ActiveRecord::NullRelationActiveRecord::Relation#none,对 Relation 类实现空对象模式;

  • 新增 create_join_table 迁移助手,用于创建 HABTM 中间表;

  • 支持创建 PostgreSQL hstore 记录。

弃用项:

  • 旧式基于 hash 的查找器 API 被弃用,此前接受“finder options”的方法不再支持该用法;

  • find_by_...find_by_...! 外的全部动态查找器方法被弃用。改写对照:

    • find_all_by_...where(...)
    • find_last_by_...where(...).last
    • scoped_by_...where(...)
    • find_or_initialize_by_...find_or_initialize_by(...)
    • find_or_create_by_...find_or_create_by(...)
    • find_or_create_by_...!find_or_create_by!(...)

文档与致谢

Rails 4.0 起,官方指南改用 GitHub Flavored Markdown 编写(本仓库 guides/source 目录即是其延续),并采用了响应式布局设计。

关于完整的贡献者名单与致谢,可参考 Rails 官方贡献者页面(此处不展开外部链接)。

结语:从 4.0 到当前仓库

Rails 4.0 的三大遗产——Strong Parameters、Russian doll 片段缓存、Turbolinks 式局部更新——至今仍是当代 Rails 的骨架:当前仓库中 strong_parameters.rbpermit/expect 链、cache_helper.rbcache 块与模板摘要机制、Relation#cache_keycache_key_with_version 的版本化失效设计,都是当年设计决策的直接延续。理解 4.0 发布说明中每一项特性“为什么被引入、为什么被移除”,是阅读当前 Rails 源码、做版本升级与性能/安全设计时最有价值的历史坐标。

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