深入解读 Rails 3.0 发行说明:Merb 融合带来的六项架构变革,以及它们在当前 Rails 代码库中的延续
本篇基于 Rails 官方仓库中的历史发行说明文档 3_0_release_notes.md,完整还原 Rails 3.0 从 Rails 2.x 升级的全部关键路径:Ruby 版本要求、Application 对象、script/rails、Bundler 依赖管理、全新的 Action Dispatch 路由器、无侵入式 JavaScript(UJS)、validates 验证 API、基于 Arel 的可链式查询接口,以及基于 Mail gem 重写的 Action Mailer。读完本文,你既能掌握 Rails 3.0 发行说明的全部技术要点,也能顺藤摸瓜在当前 Rails 源码仓库中找到每一项架构决策的“后代”,理解现代 Rails 的骨架是如何在那次大重构中成形的。
一、Rails 3.0 的定位:Merb 团队融合后的“大解耦”
Rails 3.0 发行说明的开头即点明了它的来路:这是 Merb 团队加入 Rails 阵营后的第一个大版本,带来了“对框架无关性的关注、更精简快速的内部实现,以及一批令人愉悦的新 API”。来自 Merb 1.x 的开发者会发现大量熟悉的面孔,而从 Rails 2.x 升级的开发者同样能平滑过渡——因为团队刻意用完善的弃用警告(deprecation warnings)包裹了所有旧 API,使得存量应用不必立即重写就能跑在 Rails 3 上。
发行说明给出的五大亮点是:
- 全新的路由器,强调 RESTful 声明式路由;
- 新的 Action Mailer API,以 Action Controller 为范本重写,彻底摆脱发送 multipart 邮件的痛苦;
- 新的 Active Record 可链式查询语言,构建在关系代数(Arel)之上;
- 无侵入式 JavaScript 助手,配套 Prototype、jQuery 等驱动,宣告行内 JS 的终结;
- 基于 Bundler 的显式依赖管理。
从规模上看,Rails 3.0 由近 4,000 个提交、超过 250 位作者贡献完成。发行说明本身只覆盖主要升级点,逐条 bug 修复不在其列。
安装方式非常简单,一条命令即可:
# 如环境需要可加 sudo
$ gem install rails
从 Rails 2.x 升级的前提条件
发行说明给出了明确的升级路线图:先保证良好的测试覆盖 → 升级到 Rails 2.3.5 验证应用仍正常 → 再进入 Rails 3。具体要注意的变化如下。
1. 最低 Ruby 版本为 1.8.7
Rails 3.0 要求 Ruby 1.8.7 或更高,同时兼容 Ruby 1.9.2。发行说明附有一条重要的历史提示:
- Ruby 1.8.7 p248/p249 存在序列化(marshalling)bug,会导致 Rails 3.0 崩溃(REe 1.8.7-2010.02 起已修复);
- Ruby 1.9.1 在 Rails 3.0 上会直接段错误,不可用;想用 1.9.x 就选 1.9.2。
2. Rails Application 对象
为支持“同一进程中运行多个 Rails 应用”,Rails 3 引入了 Application 对象:它持有全部应用级配置,性质上相当于旧版 config/environment.rb。每个 Rails 应用都必须在 config/application.rb 中定义对应的应用对象;升级时需要新建该文件,并把 config/environment.rb 中的相应配置迁移过去。
3. script/* 被 script/rails 取代
新的 script/rails 取代了 script 目录下的所有脚本,但它不直接执行——rails 命令检测到在应用根目录中被调用时,会自动转手执行对应脚本。惯用方式为:
$ rails console # 取代 script/console
$ rails g scaffold post title:string # 取代 script/generate scaffold post title:string
rails --help 可列出全部选项。
4. config.gem 退役,Bundler 接管
config.gem 方法被彻底移除,由 Bundler 加 Gemfile 取代(详见下文“Gemfile 与本地打包”)。
升级辅助工具:rails_upgrade 插件
发行说明推荐了官方的 rails_upgrade 插件来自动化升级流程。安装后运行 rake rails:upgrade:check 即可检查应用中需要更新的部分(并附更新指引);它还能根据现有 config.gem 调用生成 Gemfile,并根据现有路由文件生成新的 routes 文件:
$ ruby script/plugin install git://github.com/rails/rails_upgrade.git
二、创建 Rails 3.0 应用与 Gemfile 依赖管理
新建应用的标准姿势:
# 前提:已安装 rails RubyGem
$ rails new myapp
$ cd myapp
Gemfile 与本地打包(Vendoring Gems)
Rails 3 起,应用根目录的 Gemfile 决定了启动所需的全部 gem。该文件由 Bundler 处理并安装依赖,还可以把依赖全部安装到应用本地,使应用不再依赖系统级 gem。
这一改变直接淘汰了旧机制:既然可以用 bundle 命令把应用依赖“冻结”,rake freeze 便失去意义并被移除。发行说明提供了两个面向“追新”开发者的开关:
# 从 Git 仓库直接拉取 Rails 主干
$ rails new myapp --edge
# 使用本地的 Rails 检出目录生成应用
$ ruby /path/to/rails/bin/rails new myapp --dev
此外,应用生成器新增了若干跳过选项,可跳过 test-unit、Active Record、Prototype 和 Git 的安装。--dev 标志会让生成的 Gemfile 指向本地的 Rails 检出目录(由 rails 二进制的路径推断)。
三、六项重大架构变革
发行说明将 Rails 3 的架构变化归纳为六点。下面逐项展开,并对照当前仓库标注这些设计的落点。
1. Railties 重造(Restrung)
Railties 被更新为“整个 Rails 框架一致的插件 API”,同时彻底重写了生成器和 Rails 绑定。结果是:开发者可以在一致的、定义明确的方式下,挂接到生成器与应用框架的任何重要阶段。当前仓库中,这一层的实现位于 railties/lib/rails,其中包含 150 余个 Ruby 文件与 130 余个生成器模板,正是当年“生成器完全重写”之后的产物。
2. 核心组件全面解耦(The Great Decoupling)
Merb 与 Rails 合并后的大工程,就是拆除核心组件之间的紧耦合。达成之后,所有核心组件都使用与插件开发相同的 API——任何插件、任何核心组件替代品(如 DataMapper、Sequel)都能获得与核心组件同等的扩展能力。
3. Active Model 抽象层
解耦的一部分是把 Action Pack 对 Active Record 的所有依赖全部抽出。完成后,新 ORM 插件只需实现 Active Model 接口即可与 Action Pack 无缝协作。在当前仓库中,这一抽象层独立为 activemodel 组件,activemodel/lib/active_model 下可见 validations.rb、translation.rb、callbacks.rb、naming.rb 等模块,其中 validator.rb 与 validations 目录正是下文 validates 新 API 的实现所在。
4. AbstractController 控制器抽象
为了把“渲染视图”等行为从 HTTP 概念中剥离,Rails 3 创建了与 HTTP 无关的基类 AbstractController,使 ActionController 与 ActionMailer 得以大幅简化:公共代码被抽到 Abstract Controller 中,消除了各库间的重复。当前仓库中它位于 actionpack/lib/abstract_controller,base.rb、rendering.rb、translation.rb 等模块即是当年抽象的直接延续。
5. Arel 集成
Arel(Active Relation)被纳入 Active Record 的底层并成为 Rails 的必需组件。它提供 SQL 抽象,简化了 Active Record 本体,并为 Active Record 的关系(relation)能力提供了基础。当前仓库中,Arel 作为 activerecord/lib/arel 目录完整保留,是查询接口可链式调度的执行引擎。
6. Mail 提取
Action Mailer 自诞生起就背着猴子补丁、预解析器、投递/接收代理,甚至在源码树里 vendored 了 TMail。Rails 3 将所有邮件消息相关功能抽象到独立的 Mail gem,减少了代码重复,并在 Action Mailer 与邮件解析器之间划出可定义的边界。这一决定的现代形态在 actionmailer/lib/action_mailer/base.rb 中依然清晰可见:ActionMailer::Base 的 initialize 中直接 @_message = Mail.new(base.rb#L656),整个 Action Mailer 只是 Rails DSL 加 Mail gem 的封装。
四、Railties 的具体变化
解耦使 Railties 得到一次大手术,目标是让接入框架、引擎、插件尽可能无痛且可扩展:
- 应用命名空间:每个应用拥有自己的命名空间,应用启动形如
YourAppName.boot,便于与其他应用共存交互; Rails.root/app全量加入加载路径:例如创建app/observers/user_observer.rb即可被自动加载,无需任何配置;Rails.config对象:Rails 3.0 起提供Rails.config作为全局配置的中心仓库。
生成器的彻底重写
Rails 3.0 中生成器受到的关注度极高,核心结论:
- 生成器被完全重写,与旧版本不向后兼容;
- 旧的 Rails 模板 API 与生成器 API 合并为同一套;
- 生成器不再从特殊路径加载,而是按 Ruby 加载路径查找——
rails generate foo会寻找generators/foo_generator; - 新生成器提供钩子(hooks),任何模板引擎、ORM、测试框架都能方便地挂接;
- 支持模板覆盖:在
Rails.root/lib/templates放一份副本即可替换生成模板; - 提供
Rails::Generators::TestCase用于编写和测试自定义生成器。
当前仓库中,这一套体系演化成了 railties/lib/rails/generators 目录——本仓库中 rails new、rails generate 等命令的所有模板与逻辑都源于这次重写。
生成视图与 rake 任务的改进
- 生成的视图改用
div标签,替代原来的p标签; - Scaffold 生成的页面开始使用
_form局部模板,避免 new/edit 视图中的重复代码; - Scaffold 表单使用
f.submit,根据传入对象的状态自动输出 "Create ModelName" 或 "Update ModelName"。
rake 任务方面新增:
rake db:forward:按单个或分组方式向前滚动执行迁移;rake routes CONTROLLER=x:只查看某一个控制器的路由。
Railties 层面的弃用项
RAILS_ROOT弃用,改用Rails.root;RAILS_ENV弃用,改用Rails.env;RAILS_DEFAULT_LOGGER弃用,改用Rails.logger;PLUGIN/rails/tasks与PLUGIN/tasks不再被加载,所有任务必须放在PLUGIN/lib/tasks。
五、Action Pack:路由、控制器与视图的全面换代
Abstract Controller
Abstract Controller 把 Action Controller 中通用的部分抽成可复用模块:模板渲染、局部模板、助手、翻译、日志、请求-响应周期的任何环节,任何库都可以直接使用。它使 ActionMailer::Base 可以直接继承 Abstract Controller,只需把 Rails DSL 包在 Mail gem 上。需要注意:Abstract Controller 不是面向用户的 API,日常开发中基本不会直接接触它。
Action Controller
- 生成的
application_controller.rb默认开启protect_from_forgery; cookie_verifier_secret弃用,改由Rails.application.config.cookie_secret配置,并独立到config/initializers/cookie_verification_secret.rb;session_store的配置从ActionController::Base.session迁移到Rails.application.config.session_store,默认值设在config/initializers/session_store.rb;- 新增
cookies.secure,可用cookies.secure[:key] => value写入加密 cookie 值; - 新增
cookies.permanent,可写入cookies.permanent[:key] => value,验证失败时会抛出异常; respond_to块内的format调用可直接传:notice => 'This is a flash message'或:alert => 'Something went wrong',flash[]的原有用法不变;- 新增
respond_with方法,简化经典的format块写法; - 新增
ActionController::Responder,让响应生成方式更灵活; - 弃用:
filter_parameter_logging被config.filter_parameters << :password取代。
Action Dispatch:重写后的路由器
Action Dispatch 是 Rails 3.0 的新组件,提供了更干净的路由实现:
- 路由器大幅重写:Rails 路由器基于
rack_mount并覆以 Rails DSL,成为一块可独立使用的软件。这一路线在当代仓库中被继承并演进——如今路由核心已内置在 actionpack/lib/action_dispatch/journey 中,router.rb、routes.rb、parser.rb等模块共同构成不再依赖 rack_mount 的原生实现; - 路由被命名空间化到应用模块内:
# 旧写法(Rails 2.x):
ActionController::Routing::Routes.draw do |map|
map.resources :posts
end
# 新写法(Rails 3):
AppName::Application.routes do
resources :posts
end
- 新增
match方法,且匹配到的路由可以指向任意 Rack 应用; - 新增
constraints方法,用约束守卫路由; - 新增
scope方法,为不同语言或不同动作对路由命名空间化,例如:
scope 'es' do
resources :projects, :path_names => { :edit => 'cambiar' }, :path => 'proyecto'
end
# 得到编辑动作的 URL:/es/proyecto/1/cambiar
- 新增
root方法,作为match '/', :to => path的快捷方式; match支持可选段,如match "/:controller(/:action(/:id))(.:format)",括号内各段均为可选;- 路由可以用块表达,例如
controller :home { match '/:action' }。
注意:旧式 map 命令在 3.0 中仍可通过兼容层工作,但该兼容层将在 3.1 中移除。
当前仓库中,这些 DSL 方法的实现可以在 actionpack/lib/action_dispatch/routing/mapper.rb 中逐一找到:match(mapper.rb#L1848)、scope(mapper.rb#L1000)、constraints(mapper.rb#L1187)与 root(mapper.rb#L1914),十余年间签名不断扩展,但骨架与 Rails 3 引入时一致。
Action Dispatch 的弃用项:
- 面向非 REST 应用的万能路由(
/:controller/:action/:id)在新生成应用中被注释掉; - 路由的
:path_prefix不复存在,:name_prefix现在会自动在值末尾追加_。
Action View
无侵入式 JavaScript(UJS)
Action View 助手经历了大重写:实现 UJS 钩子、移除旧式行内 AJAX 命令,从而允许 Rails 使用任何符合 UJS 规范的驱动。具体影响:
- 所有
remote_<method>助手从 Rails 核心中移除,移入 Prototype Legacy Helper gem; - 要让 HTML 带 UJS 钩子,改为传
:remote => true。例如:
form_for @post, :remote => true
产出:
<form action="http://host.com" id="create-post" method="post" data-remote="true">
块式助手改用 <%=
form_for、div_for 这类从块中插入内容的助手,模板中改用 <%=:
<%= form_for @post do |f| %>
...
<% end %>
自己写的同类助手应返回字符串,而不是手工追加输出缓冲区。而 cache、content_for 这类行为不同的助手不受影响,仍用 <%。
其他视图变化
- 不再需要
h(string)手动转义:所有视图模板默认开启 HTML 转义,需要原样输出时用raw(string); - 助手默认输出 HTML5;
- 表单标签助手支持单参数 I18n 取值:
f.label :name直接取:name的翻译; - I18n 的 select 标签键从
:en.support.select调整为:en.helpers.select; - ERB 插值不再需要末尾减号来消除 HTML 输出中的多余换行;
- 新增
grouped_collection_select助手; - 新增
content_for?,可在渲染前检查视图内容是否已存在; - 表单助手传
:value => nil会把字段value置为 nil,而不是回落到默认值; - 表单助手传
:id => nil使字段不渲染id属性; image_tag传:alt => nil使img标签不渲染alt属性。
六、Active Model:validates 与自定义验证器
Active Model 是 Rails 3.0 的新组件,为 ORM 提供与 Rails 交互的抽象层。校验逻辑从 Active Record 移入 Active Model,形成跨 ORM 的统一接口,核心变化是新的 validates :attribute, options_hash 快捷方法,可一次传入多种校验选项。validates 支持的选项:
| 选项 | 说明 |
|---|---|
:acceptance => Boolean |
接受校验 |
:confirmation => Boolean |
确认校验 |
:exclusion => { :in => Enumerable } |
排除校验 |
:inclusion => { :in => Enumerable } |
包含校验 |
:format => { :with => Regexp, :on => :create } |
格式校验 |
:length => { :maximum => Fixnum } |
长度校验 |
:numericality => Boolean |
数值校验 |
:presence => Boolean |
非空校验 |
:uniqueness => Boolean |
唯一性校验 |
注意:Rails 2.3 风格的 validates_xxx_of 方法在 3.0 中全部保留,新的 validates 是附加便利而非替代。
还可以传递可复用的验证器对象,在多个使用 Active Model 的对象间共享:
class TitleValidator < ActiveModel::EachValidator
Titles = ['Mr.', 'Mrs.', 'Dr.']
def validate_each(record, attribute, value)
unless Titles.include?(value)
record.errors[attribute] << 'must be a valid title'
end
end
end
class Person
include ActiveModel::Validations
attr_accessor :title
validates :title, :presence => true, :title => true
end
# Active Record 中同样写法:
class Person < ActiveRecord::Base
validates :title, :presence => true, :title => true
end
同时提供内省能力:
User.validators
User.validators_on(:login)
这套 API 在当代源码中依然原样可考:activemodel/lib/active_model/validations.rb 定义了 validates 入口,ActiveModel::EachValidator 位于 activemodel/lib/active_model/validator.rb,validators / validators_on 内省接口亦保留至今。
七、Active Record:可链式查询接口与适配器修复
Rails 3.0 中 Active Record 得到大量关注:抽象进 Active Model、基于 Arel 全面更新查询接口、验证升级,以及大量增强与修复。所有 Rails 2.x API 通过兼容层可用,该兼容层支持到 3.1。
查询接口(Query Interface)
借助 Arel,Active Record 的核心方法现在返回 relation。2.3.x 的既有 API 在 3.1 之前不弃用、3.2 之前不移除,但新 API 提供以下可串联的方法:
| 方法 | 作用 |
|---|---|
where |
设定 relation 的筛选条件 |
select |
选择要返回的模型属性 |
group |
按指定属性分组 |
having |
限定分组(GROUP BY 约束) |
joins |
把 relation 连接到另一张表 |
clause |
限定连接关系(JOIN 约束) |
includes |
预加载关联 |
order |
按表达式排序 |
limit |
限制返回记录数 |
lock |
锁定返回的记录 |
readonly |
返回只读副本 |
from |
从多张表选择关系 |
scope |
(原 named_scope)返回 relation,可与其他 relation 方法串联 |
with_scope / with_exclusive_scope |
现在也返回 relation,可串联 |
default_scope |
同样与 relation 协作 |
在当代代码库中,这套作用域系统对应 activerecord/lib/active_record/scoping/named.rb(scope/with_scope)与 activerecord/lib/active_record/scoping/default.rb(default_scope)。
增强项
- 新增
destroyed?判断; - 关联新增
inverse_of,可直接取回已加载关联的实例而无需再查库。
补丁与弃用
修复与适配方面:SQLite 2 支持移除(转向 SQLite 3);MySQL 支持列顺序;PostgreSQL 适配器的 TIME ZONE 不再写入错误值、支持表名带多 schema、支持 XML 数据类型列;table_name 现在会缓存;Oracle 适配器经历大量 bug 修复。弃用清单:
named_scope弃用,更名为scope;scope中应改用 relation 方法而非:conditions => {}风格查找,例如scope :since, lambda { |time| where("created_at > ?", time) };save(false)弃用,改用save(:validate => false);- Active Record 的 I18n 错误消息键从
:en.activerecord.errors.template改为:en.errors.template; model.errors.on弃用,改用model.errors[];validates_presence_of迁移为validates ... :presence => true风格;ActiveRecord::Base.colorize_logging与config.active_record.colorize_logging弃用,改用Rails::LogSubscriber.colorize_logging或config.colorize_logging。
另有一条值得留意的说明:State Machine 虽在 Active Record 主干上存在数月,但最终没有进入 Rails 3.0 发布版。
八、Active Resource:接入 Active Model
Active Resource 同样被抽取到 Active Model 体系,使其对象可与 Action Pack 无缝配合。3.0 中的变化清单相当长:
- 通过 Active Model 获得验证能力;
- 新增 observer 钩子;
- 支持 HTTP 代理;
- 支持摘要认证(digest authentication);
- 模型命名逻辑移入 Active Model;
- 属性改为 indifferent access 的 Hash;
- 新增
first、last、all作为等价 find scope 的别名; find_every在无结果时不再抛ResourceNotFound;- 新增
save!,对象valid?不成立时抛ResourceInvalid; - 新增
update_attribute与update_attributes; - 新增
exists?; SchemaDefinition更名为Schema,define_schema更名为schema;- 加载远程错误时改用 Active Resource 的
format而非响应content-type; - schema 块改用
instance_eval; - 识别 410 响应为资源已被删除;
- 支持为连接设置 SSL 选项;
- 设置连接超时同时影响
Net::HTTP的open_timeout。
弃用项:save(false) 改为 save(:validate => false);Ruby 1.9.2 下 URI.parse 与 URI.decode 不再使用。
九、Active Support:可摘选化(cherry pickable)
Rails 3 对 Active Support 的重点工程是“摘选化”:不再需要 require 整个库才能使用其中一块,让各核心组件跑得更轻。主要变化:
- 大规模清理,移除全库各处不再使用的方法;
- 不再内置 vendored 的 TZInfo、Memcache Client 与 Builder,改为依赖项,经
bundle install安装; - 安全缓冲区实现于
ActiveSupport::SafeBuffer; - 新增
Array.uniq_by与Array.uniq_by!; - 移除
Array#rand,从 Ruby 1.9 回移Array#sample; - 修复
TimeZone.seconds_to_utc_offset返回值错误的 bug; - 新增
ActiveSupport::Notifications中间件——如今 Rails 全框架的 instrumentation 事件总线正是这一组件; ActiveSupport.use_standard_json_time_format默认值改为true;ActiveSupport.escape_html_entities_in_json默认值改为false;Integer#multiple_of?接受 0 作为参数,接收者非 0 时返回 false;string.chars更名为string.mb_chars;ActiveSupport::OrderedHash支持 YAML 反序列化;- XmlMini 新增基于 LibXML/Nokogiri 的 SAX 解析器;
- 新增
Object#presence(#present?为真返回自身,否则返回nil); - 新增
String#exclude?(#include?的反义)与Enumerable#exclude?; DateTime补上to_i,使含DateTime属性的模型to_yaml正确工作;- XSS 转义在 Rails 中默认开启;
HashWithIndifferentAccess支持深度合并(deep-merge);Enumerable#sum兼容不响应:size的枚举;- 零长度时长的
inspect返回'0 seconds'而非空串; ModelName新增element与collection;String#to_time与String#to_datetime处理小数秒;- 新回调支持响应
:before/:after的 around filter 对象; ActiveSupport::OrderedHash#to_a返回有序数组对,与 Ruby 1.9 的Hash#to_a对齐;MissingSourceFile常量保留但仅等于LoadError;- 新增
Class#class_attribute:声明可被子类继承与覆写的类级属性; - 移除
ActiveRecord::Associations中的DeprecatedCallbacks; Object#metaclass更名为Kernel#singleton_class,与 Ruby 对齐。
以下方法因 Ruby 1.8.7/1.9 已内置而移除:Integer#even? / Integer#odd?、String#each_char、String#start_with? / String#end_with?(第三人称别名保留)、String#bytesize、Object#tap、Symbol#to_proc、Object#instance_variable_defined?、Enumerable#none?。
以下方法因框架内部不再使用而移除:Kernel#daemonize、Object#remove_subclasses_of、Object#extend_with_included_modules_from、Object#extended_by、Class#remove_class、Regexp#number_of_captures、Regexp.unoptionalize、Regexp.optionalize。
REXML 的安全补丁保留在 Active Support 中,因为 Ruby 1.8.7 的早期补丁级仍需要它,Active Support 会自动判断是否需要应用。
十、Action Mailer:继承 Abstract Controller 的完全重写
Action Mailer 换用 Mail gem 取代 TMail,代码几乎逐行重写:它现在直接继承 Abstract Controller,把 Mail gem 包在 Rails DSL 里,代码量与重复度大幅下降。发行说明列出的行为变化:
- 所有 mailer 默认放在
app/mailers(放在app/models的做法被弃用); - 新 API 由三个方法组成:
attachments、headers与mail; - 原生支持内联附件,使用
attachments.inline; - 邮件方法返回
Mail::Message对象,对其调用deliver即可发送(ActionMailer.deliver(message)被弃用,直接message.deliver); - 所有投递方式抽象进 Mail gem;
mail方法可接收包含全部合法邮件头字段的 hash;mail的作用类似 Action Controller 的respond_to:可显式或隐式渲染模板,Action Mailer 会按需把邮件转成 multipart;format.mime_type块内可传 proc,显式渲染特定文本类型,或添加布局、不同模板;proc 内的render来自 Abstract Controller,支持相同选项;- 原 mailer 单元测试迁为功能测试;
- 头部与正文的自动编码全部委托给 Mail gem,Action Mailer 会自动为邮件正文和头编码。
当前仓库中这段设计完整可考:actionmailer/lib/action_mailer/base.rb#L611 中 mail 方法签名演化为 mail(...) 并返回 MessageDelivery(deliver/deliver_later 的执行载体),base.rb#L731 与 base.rb#L769 仍是 headers 与 attachments 三个核心方法之二——十余年后,"mail + headers + attachments" 的三元组依然是 Action Mailer 的形态。
Action Mailer 的弃用项:
:charset、:content_type、:mime_version、:implicit_parts_order弃用,改用ActionMailer.default :key => value风格的声明;- 动态的
create_method_name/deliver_method_name弃用,直接调用method_name,其返回Mail::Message对象; ActionMailer.deliver(message)弃用,改为message.deliver;template_root弃用,改为在mail块的format.mime_typeproc 中向render传选项;- 用
body { :ivar => value }定义实例变量的做法弃用,直接在方法内声明实例变量,视图即可使用。
十一、文档与国际化:3.0 时代的配套工作
发行说明还交代了两件配套事项。其一,国际化方面投入巨大:新版 I18n gem 带来多项速度改进;ActiveModel::Translation 与 ActiveModel::Validations 可让任意对象获得 I18n 行为,并有 errors.messages 兜底翻译;属性可带默认翻译;表单提交标签会根据对象状态自动取 Create/Update 对应翻译;标签助手只传属性名即可走 I18n。其二,文档体系上,仓库内 API 文档随改动更新,Edge Guides 逐一同步 3.0 的变化;本仓库中这份发行说明本身即存放于 guides/source/3_0_release_notes.md,与其他各版本发行说明(2.2 至 8.2)并列,由 Mikel Lindsaar 整理成文。
结语:为什么今天仍要读这份 3.0 发行说明
把这份 2010 年的发行说明放回当前仓库对照阅读,会发现它是一份极其精确的“架构考古索引”:Application 对象与 Rails.config 演化为 railties/lib/rails 的应用初始化体系;rack_mount 路由器演化为 actionpack/lib/action_dispatch/journey 原生 Journey 引擎;validates 与自定义验证器完整保留在 activemodel/lib/active_model;mail/headers/attachments 三元组仍在 actionmailer/lib/action_mailer/base.rb 中服役;Arel 依旧以 activerecord/lib/arel 的形态支撑着可链式查询。理解 Rails 3.0 这六项架构变革与数十项 API 更迭,就是理解现代 Rails 骨架从何而来的最短路径。
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 StartedRust0624
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