Ruby on Rails 2.3 发布说明精读:Rack 集成、嵌套事务与统一渲染的演进
本文基于 Rails 官方发布说明文档 guides/source/2_3_release_notes.md,完整梳理 Rails 2.3 这一里程碑版本的核心变化:Rack 全面集成与中间件栈、Rails 引擎复兴、Active Record 的嵌套属性与嵌套事务、动态/默认作用域、find_each 批处理、统一 render、HTTP Digest 认证、Rails Metal、应用模板与安静回溯(quiet backtraces)等。结合当前 Rails 仓库源码中的对应实现(如 batches.rb、nested_attributes.rb),读者既能掌握 2.3 各特性的用法与迁移要点,也能理解这些 API 在当前代码库中的演进脉络。
一、应用架构:Rack 全面集成
Rails 2.3 的架构层面有两个大变化:与模块化 Web 服务器接口 Rack 的完全集成,以及对 Rails 引擎(可嵌入其他应用的 Rails 应用)的支持重新加强。官方提醒:由于内部改动巨大,升级到 2.3 后应在本地与生产环境分别测试会话、Cookie、文件上传和 JSON/XML API。
Rack 集成要点
2.3 的 Rack 相关变化(继承自原文档的完整清单):
script/server改为基于 Rack,因此支持任意 Rack 兼容服务器;它会自动查找 rackup 配置文件(默认config.ru,可用-c开关覆盖)。- FCGI 处理器改为走 Rack。
ActionController::Dispatcher维护自己的默认中间件栈,中间件可注入、重排和移除,栈在启动时编译成链;可在environment.rb中配置。- 新增
rake middleware任务用于查看中间件栈,方便调试中间件顺序。 - 集成测试运行器改为执行整个中间件与应用栈,使集成测试成为测试 Rack 中间件的最佳场景。
ActionController::CGIHandler是对 Rack 的向后兼容 CGI 封装,负责把旧 CGI 对象的环境信息转换为 Rack 形式。CgiRequest与CgiResponse被移除。- 会话存储改为懒加载:请求中若从不访问 session 对象,就不会解析 cookie、读 memcache 或查 ActiveRecord 记录。
- 测试中设置 cookie 不再需要
CGI::Cookie.new,直接给request.cookies["foo"]赋值字符串即可。 - 会话存储类迁移:
CGI::Session::CookieStore→ActionController::Session::CookieStore;CGI::Session::MemCacheStore→ActionController::Session::MemCacheStore;CGI::Session::ActiveRecordStore→ActiveRecord::SessionStore;仍然可以用ActionController::Base.session_store = :active_record_store切换。 - 会话默认选项仍通过
ActionController::Base.session = { :key => "..." }设置,但:session_domain选项改名为:domain。 - 原本包裹整个请求的互斥锁移入中间件
ActionController::Lock。 ActionController::AbstractRequest与ActionController::Request合并,新的ActionController::Request继承自Rack::Request;这影响测试请求中response.headers['type']的访问,应改用response.content_type。- 若加载了 ActiveRecord,
ActiveRecord::QueryCache中间件会自动插入中间件栈,负责建立并清空按请求隔离的查询缓存。 - 路由器与控制器类遵循 Rack 规范,可以直接用
SomeController.call(env)调用控制器;路由参数存放在rack.routing_args中。 - 配置会话键的写法从
config.action_controller.session = { :session_key => 'foo', ... }改为{ :key => 'foo', ... }。 ParamsParser中间件会预处理 XML、JSON 或 YAML 请求体,使后续任何Rack::Request都能正常读取。
引擎(Engines)支持的复兴
Rails 2.3 为引擎提供了几项新能力:引擎中的路由文件现在会和 routes.rb 一样被自动加载与重新加载(其他插件的路由文件同理);若插件带有 app 文件夹,app/[models|controllers|helpers] 会自动加入 Rails 加载路径;引擎还支持添加视图路径,Action Mailer 与 Action View 都会使用来自引擎及其他插件的视图。
二、Ruby 1.9.1 支持
Rails 2.3 在 Ruby 1.8 与当时刚发布的 Ruby 1.9.1 下都应通过全部自有测试。但迁移到 1.9.1 需要自行核查所有数据适配器、插件和依赖代码对 1.9.1 的兼容性,而不只是 Rails 核心本身。
三、Active Record:嵌套属性、嵌套事务与批处理
嵌套属性(Nested Attributes)
Active Record 可以在你显式声明后,直接更新嵌套模型的属性:
class Book < ActiveRecord::Base
has_one :author
has_many :pages
accepts_nested_attributes_for :author, :pages
end
开启嵌套属性带来几项能力:记录与其关联子记录的自动(且原子的)一起保存、感知子记录的校验,以及嵌套表单(见 Action View 部分)。还可以用 :reject_if 选项为新记录的加入设置过滤条件:
accepts_nested_attributes_for :author,
:reject_if => proc { |attributes| attributes['name'].blank? }
从当前仓库源码看,nested_attributes.rb 中的 accepts_nested_attributes_for 至今仍是这套签名:默认 allow_destroy: false, update_only: false,合法选项为 allow_destroy、reject_if、limit、update_only,且 reject_if: :all_blank 会被映射到内置的“全空即拒绝”过程对象——2.3 引入的选项空间在十余年后几乎原样保留。
嵌套事务(Nested Transactions)
2.3 实现了长期呼声很高的嵌套事务,你可以写出这样的代码:
User.transaction do
User.create(:username => 'Admin')
User.transaction(:requires_new => true) do
User.create(:username => 'Regular')
raise ActiveRecord::Rollback
end
end
User.find(:all) # => 只返回 Admin
嵌套事务允许回滚内层事务而不影响外层事务状态。必须显式加上 :requires_new 选项才会产生嵌套,否则内层事务只是并入父事务(与 Rails 2.2 行为一致)。底层机制是 savepoint,因此即使数据库不支持真正的嵌套事务也能工作;此外,还有一套机制保证嵌套事务在测试的事务性 fixture 下正常工作。
这一点在当前源码中依然成立:transaction.rb 中的 SavepointTransaction 通过 connection.create_savepoint(savepoint_name) / rollback_to_savepoint / release_savepoint 管理保存点,与 2.3 发布说明描述的“用 savepoint 模拟嵌套事务”的机制一脉相承。
动态作用域(Dynamic Scopes)
在动态查找器(find_by_color_and_flavor 这类即兴方法)与命名作用域(把可复用查询条件封装成 currently_active 这样的好名字)之外,2.3 新增了动态作用域方法:允许边链式调用边即时过滤。
Order.scoped_by_customer_id(12)
Order.scoped_by_customer_id(12).find(:all,
:conditions => "status = 'open'")
Order.scoped_by_customer_id(12).scoped_by_status("open")
使用动态作用域无需任何定义,直接可用。(从源码结构看,这种基于 method_missing 的 scoped_by_* 约定式写法在后来的版本中被 where 链式 API 取代,但 2.3 的历史定位是“让即时过滤具备方法链能力”。)
默认作用域(Default Scopes)
2.3 引入与命名作用域相似、但作用于模型内所有查询的“默认作用域”概念。例如 default_scope :order => 'name ASC' 会让该模型取出的记录始终按 name 排序(除非显式覆盖)。
批处理(Batch Processing)
2.3 提供 find_in_batches 以减小大表遍历时的内存压力:
Customer.find_in_batches(:conditions => {:active => true}) do |customer_group|
customer_group.each { |customer| customer.update_account_balance! }
end
可以把大部分 find 选项传给 find_in_batches,但有两个约束:不能指定返回顺序(始终按主键升序,且主键必须是整数),也不能使用 :limit 选项;应使用 :batch_size 选项(默认 1000)控制每批记录数。
find_each 是 find_in_batches 的包装,逐条返回记录,查询本身仍按批(默认 1000 条)进行:
Customer.find_each do |customer|
customer.update_account_balance!
end
官方建议仅在批处理场景使用此方法:少于 1000 条的小数据量直接用常规 find 加自己的循环即可。
当前仓库中这两个方法依然活跃,位于 batches.rb 与 batches.rb:签名演变为关键字参数 start:、finish:、batch_size: 1000、cursor:(可为单列或列名数组)、order:,find_each 内部实现正是逐批调用 find_in_batches 再对每批 records.each(&block)——与 2.3 发布说明描述的“find_each 是 find_in_batches 的逐条包装”完全一致。新增的 start/finish 参数正是当年多 worker 并行处理队列场景的自然延续;源码注释同样保留了“批处理天然存在竞态、游标列须可排序”的提醒。
回调支持多条件
Active Record 回调现在允许在同一回调上同时组合 :if 与 :unless,并以数组形式提供多个条件:
before_save :update_credit_rating, :if => :active,
:unless => [:admin, :cash_only]
find 支持 having
find 新增 :having 选项(has_many 与 has_and_belongs_to_many 关联同样支持),用于对分组结果过滤:
developers = Developer.find(:all, :group => "salary",
:having => "sum(salary) > 10000", :select => "salary")
MySQL 连接自动重连
MySQL 客户端支持重连标志:设为 true 时,连接丢失后客户端会先尝试重连再放弃。2.3 起可以在 database.yml 中为 MySQL 连接设置 reconnect = true 获得该行为;默认 false,不改变现有应用行为。
其他 Active Record 变化
- 移除了
has_and_belongs_to_many预加载生成 SQL 中多余的AS,对部分数据库更友好。 ActiveRecord::Base#new_record?对已存在的记录返回false而非nil。- 修复了某些
has_many :through关联中表名引用的 bug。 - 可以指定
updated_at的时间戳:cust = Customer.create(:name => "ABC Industries", :updated_at => 1.day.ago)。 find_by_attribute!失败时给出更好的错误信息。to_xml增加:camelize选项。- 修复了从
before_update或before_create中取消回调的 bug。 - 新增通过 JDBC 测试数据库的 rake 任务。
validates_length_of在提供:in或:within时会使用自定义错误消息。- 带作用域的 select 上的 count 现在正常工作,例如
Account.scoped(:select => "DISTINCT credit_limit").count。 ActiveRecord::Base#invalid?现在表现为valid?的反义。
四、Action Controller:统一渲染与路由效率
统一渲染(Unified Rendering)
ActionController::Base#render 变得更智能:你只需告诉它“渲染什么”,它会推断出“怎么渲染”。旧版通常需要显式给出选项:
render :file => '/tmp/random_file.erb'
render :template => 'other_controller/action'
render :action => 'show'
2.3 可以直接给出目标:
render '/tmp/random_file.erb'
render 'other_controller/action'
render 'show'
render :show
Rails 依据渲染目标的特征在 file、template、action 之间选择:以斜杠开头视为文件路径,内嵌斜杠视为模板路径,完全没有斜杠则视为 action;渲染 action 时符号与字符串等价。其他渲染风格(:inline、:text、:update、:nothing、:json、:xml、:js)仍需显式选项。
Application Controller 更名
一直让 application.rb 特殊命名困扰的人可以欣慰了:2.3 将其重构为 application_controller.rb。同时新增 rake 任务 rake rails:update:application_controller 自动完成迁移,该任务也会作为常规 rake rails:update 流程的一部分运行。
HTTP Digest 认证支持
2.3 内置了 HTTP Digest 认证。调用 authenticate_or_request_with_http_digest 并传入一个返回用户密码的块(密码会被哈希后与传来的凭据比较):
class PostsController < ApplicationController
Users = {"dhh" => "secret"}
before_filter :authenticate
def secret
render :text => "Password Required!"
end
private
def authenticate
realm = "Application"
authenticate_or_request_with_http_digest(realm) do |name|
Users[name]
end
end
end
这个方法在当前仓库中仍然存在,见 http_authentication.rb:实现依旧是“先尝试认证,失败则发起 Digest 认证挑战”的两段式结构,2.3 引入时的形态延续至今。
更高效的路由
2.3 的路由有两大变化:
formatted_路由助手被移除,改为直接传:format选项。这让任一资源的 route 生成过程减少 50%,还能显著节省内存(大型应用最多可达 100MB)。旧的formatted_助手暂时可用,但已被弃用。- Rails 现在支持多个路由文件,不再只有
routes.rb。可以用RouteSet#add_configuration_file随时引入更多路由,且不清除已加载的路由。这一变化对引擎最有用,但任何需要分批加载路由的应用都能受益。
基于 Rack 的懒加载会话
2.3 把 Action Controller 的会话存储底层推到了 Rack 层面。这一改动对 Rails 应用完全透明(顺带清除了围绕旧 CGI 会话处理器的一些补丁),但意义在于:非 Rails 的 Rack 应用也能访问与 Rails 应用相同的会话存储处理器(从而共享同一会话)。会话同时改为懒加载,与整个框架的加载改进保持一致——不再需要显式禁用会话,不引用即不加载。
MIME 类型处理变化
MIME::Type现在实现了=~运算符,检查带同义类型的存在性更简洁:
if content_type && Mime::JS =~ content_type
# do something cool
end
Mime::JS =~ "text/javascript" => true
Mime::JS =~ "application/javascript" => true
- 框架内部在多处检查 JavaScript 时改用
Mime::JS,统一处理这些别名。
respond_to 优化
Rails 与 Merb 团队合并后的首批成果之一:respond_to 方法经过消除一次 method_missing 调用与若干调优后,在一个在三种格式间切换的简单 respond_to 场景下,每秒可处理的请求数提升约 8%。应用代码无需任何改动即可享受这一加速。
缓存性能改进
Rails 现在维护一份按请求隔离的本地缓存,缓存从远程缓存存储读取过的内容,减少不必要的读操作。这项工作最初限于 MemCacheStore,但任何实现了所需方法的远程存储都可用。
本地化视图
Rails 可以根据已设置的 locale 提供本地化视图:Posts 控制器的 show 动作默认渲染 app/views/posts/show.html.erb;若设置了 I18n.locale = :da,则渲染 app/views/posts/show.da.html.erb;本地化模板不存在时回退到无修饰版本。Rails 还提供 I18n#available_locales 与 I18n::SimpleBackend#available_locales,返回当前项目中可用的翻译数组。
同样的机制也适用于 public 目录下的救援页:public/500.da.html 或 public/404.en.html 均可生效。
翻译的局部作用域
翻译 API 的改动让在 partial 内书写键翻译更简洁:从 people/index.html.erb 模板调用 translate(".foo"),实际等价于 I18n.translate("people.index.foo");键前不加句号则保持原有行为,不做作用域处理。
其他 Action Controller 变化
- ETag 处理更干净:响应无 body 或使用
send_file发送文件时不再发送 ETag 头。 - 移动端流量大的站点常因代理设置不当被 IP 伪造检测误伤,可以设置
ActionController::Base.ip_spoofing_check = false完全禁用该检查。 ActionController::Dispatcher实现自己的中间件栈,可通过rake middleware查看。- Cookie 会话拥有持久会话标识符,并与此前服务端存储的 API 保持兼容。
send_file与send_data的:type选项现在可接受符号,如send_file("fabulous.png", :type => :png)。map.resources的:only与:except选项不再被嵌套资源继承。- 捆绑的 memcached 客户端更新至 1.6.4.99。
expires_in、stale?、fresh_when新增:public选项,便于代理缓存。:requirements选项在额外的 RESTful member 路由上正常工作。- 浅层路由(shallow routes)正确尊重命名空间。
polymorphic_url更好地处理不规则复数名的对象。
五、Action View:嵌套表单与更聪明的 render
嵌套对象表单
只要父模型为子对象开启了嵌套属性(见 Active Record 部分),就可以用 form_for 与 fields_for 创建嵌套表单。表单可以任意深度嵌套,从而在单个视图中编辑复杂的对象层级而无需大量代码。给定模型:
class Customer < ActiveRecord::Base
has_many :orders
accepts_nested_attributes_for :orders, :allow_destroy => true
end
即可写出这样的视图:
<% form_for @customer do |customer_form| %>
<div>
<%= customer_form.label :name, 'Customer Name:' %>
<%= customer_form.text_field :name %>
</div>
<!-- 在 customer_form 构建器实例上调用 fields_for,
块会为 orders 集合的每个成员执行一次。 -->
<% customer_form.fields_for :orders do |order_form| %>
<p>
<div>
<%= order_form.label :number, 'Order Number:' %>
<%= order_form.text_field :number %>
</div>
<!-- 模型中的 allow_destroy 选项启用子记录的删除。 -->
<% unless order_form.object.new_record? %>
<div>
<%= order_form.label :_delete, 'Remove:' %>
<%= order_form.checkbox :_delete %>
</div>
<% end %>
</p>
<% end %>
<%= customer_form.submit %>
<% end %>
分片(Partial)的智能渲染
render 变得更进一步聪明:当你有一个对象或集合,且命名与某个 partial 匹配时,直接渲染对象即可。在“命名合理”的前提下:
# 等价于 render :partial => 'articles/_article',
# :object => @article
render @article
# 等价于 render :partial => 'articles/_article',
# :collection => @articles
render @articles
日期选择辅助方法的提示(Prompts)
2.3 允许为各日期选择辅助方法(date_select、time_select、datetime_select)提供自定义提示,用法与集合选择辅助方法一致:可以传提示字符串,或为各组件分别提供提示的 hash;也可以直接把 :prompt 设为 true 使用通用提示。
select_datetime(DateTime.now, :prompt => true)
select_datetime(DateTime.now, :prompt => "Choose date and time")
select_datetime(DateTime.now, :prompt =>
{:day => 'Choose day', :month => 'Choose month',
:year => 'Choose year', :hour => 'Choose hour',
:minute => 'Choose minute'})
资产时间戳缓存
Rails 向来在静态资产路径上加时间戳作为“缓存破坏器”,避免修改服务器上的图片/样式表后浏览器继续命中旧缓存。2.3 新增 Action View 配置项 cache_asset_timestamps 来改变这一行为:启用后,Rails 只在首次提供某资产时计算一次时间戳并保存该值——减少昂贵的文件系统调用,代价是服务器运行期间修改资产不会被客户端感知。
资产主机(Asset Host)可以是对象
资产主机支持声明为一个响应 call 的具体对象,使你可以为资产托管实现任意复杂逻辑。
grouped_options_for_select 辅助方法
Action View 已有的 select 辅助方法家族再添一员:grouped_options_for_select。它接受字符串数组或 hash,转换为用 optgroup 标签包裹的 option 标签串。例如:
grouped_options_for_select([["Hats", ["Baseball Cap","Cowboy Hat"]]],
"Cowboy Hat", "Choose a product...")
返回:
<option value="">Choose a product...</option>
<optgroup label="Hats">
<option value="Baseball Cap">Baseball Cap</option>
<option selected="selected" value="Cowboy Hat">Cowboy Hat</option>
</optgroup>
表单 select 辅助方法的禁用选项
表单 select 辅助方法(如 select、options_for_select)现在支持 :disabled 选项,可取单个值或值的数组:
select(:post, :category, Post::CATEGORIES, :disabled => 'private')
返回:
<select name="post[category]">
<option>story</option>
<option>joke</option>
<option>poem</option>
<option disabled="disabled">private</option>
</select>
还可以用匿名函数在运行时决定集合中哪些选项被选中和/或禁用:
options_from_collection_for_select(@product.sizes, :name, :id, :disabled => lambda{|size| size.out_of_stock?})
模板加载缓存说明
2.3 允许按环境开启或关闭模板缓存。缓存模板带来速度提升(渲染时不再检查模板文件是否更新),但意味着不重启服务器就无法“即时”替换模板。多数情况下你希望生产环境开启,在 production.rb 中设置:
config.action_view.cache_template_loading = true
新建的 2.3 应用会默认生成这行配置;从旧版本升级的应用则默认在生产与测试环境缓存模板、开发环境不缓存。
其他 Action View 变化
- CSRF 令牌生成简化:改用
ActiveSupport::SecureRandom生成的随机字符串,不再摆弄 session ID。 auto_link现在正确地把:target、:class等选项应用到生成的邮件链接上。autolink辅助方法重构,更整洁直观。current_page?在 URL 含多个查询参数时也能正常工作。
六、Active Support:Object#try 与可替换的 XML 解析器
Object#try
很多人已经习惯用 try() 来尝试对对象执行操作,在视图中尤为有用——可以避开 nil 检查:<%= @person.try(:name) %>。2.3 把它做进了 Rails 核心:对私有方法会抛出 NoMethodError,对象为 nil 时恒返回 nil。
当前仓库中该实现位于 try.rb:无参带块时执行块,respond_to? 命中时用 public_send 调用(私有方法自然不可达,行为与 2.3 的描述一致),nil 上的 try 亦直接返回 nil(try.rb)。
Object#tap 回填
Object#tap 是 Ruby 1.9(及 1.8.7)新增的方法,与 Rails 一直提供的 returning 类似:把对象交给块执行,然后返回被 yield 的对象。2.3 起 Rails 为旧版本 Ruby 补齐了这一能力。
XmlMini 可替换解析器
Active Support 的 XML 解析支持改为可插拔:默认使用标准 REXML 实现,但若安装了相应 gem,可以切换到更快的 LibXML 或 Nokogiri 实现:
XmlMini.backend = 'LibXML'
这一设计在当前源码中完整保留,见 xml_mini.rb:backend= 把名称转成对应模块赋值给 @backend,还支持线程级别的 with_backend 临时切换——2.3 引入的“可替换解析器”思路在后续版本里被进一步细化为线程局部后端。
TimeWithZone 的分数秒
Time 与 TimeWithZone 都提供 xmlschema 方法返回 XML 友好的时间字符串。2.3 起 TimeWithZone 支持与 Time 相同的参数,用于指定返回字符串中分数秒部分的位数:
Time.zone.now.xmlschema(6) # => "2009-01-16T13:00:06.13653Z"
JSON 键引用
按 JSON 规范,结构中所有键都必须是带双引号的字符串。自 2.3 起,Rails 对数字键也做了正确引用处理。
其他 Active Support 变化
Enumerable#none?用于检查没有元素匹配给定块。- Active Support 委托的
:allow_nil新选项:目标对象为 nil 时返回nil而不是抛异常。 ActiveSupport::OrderedHash新增each_key与each_value。ActiveSupport::MessageEncryptor提供一种简单方式,为存放到不可信位置(如 cookie)的信息加密。from_xml不再依赖 XmlSimple,Rails 自带仅含所需功能的 XmlMini 实现,摆脱了长期捆绑的 XmlSimple。- 被 memoize 的私有方法,其结果现在也是私有的。
String#parameterize接受可选分隔符:"Quick Brown Fox".parameterize('_') => "quick_brown_fox"。number_to_phone现在接受 7 位电话号码。ActiveSupport::Json.decode现在能处理\u0000样式的转义序列。
七、Railties:Rails Metal、应用模板与安静回溯
Rails Metal
Rails Metal 是一种在 Rails 应用内提供超快端点的新机制。Metal 类绕过路由与 Action Controller,以放弃 Action Controller 全部功能为代价换取原始速度。它建立在“让 Rails 成为具有暴露中间件栈的 Rack 应用”这一系列基础工作之上。Metal 端点可以从应用或插件中加载。
应用模板(Application Templates)
2.3 吸收了 Jeremy McAnally 的 rg 应用生成器:模板化应用生成直接内置进 Rails。如果你有每个应用都要包含的一组插件(以及众多其他用途),只需配置一次模板,之后运行 rails 命令即可反复使用。另有 rake 任务把模板应用到已有应用:
$ rake rails:template LOCATION=~/template.rb
模板的变更会叠加在项目现有代码之上。
安静的回溯(Quiet Backtraces)
基于 thoughtbot 的 Quiet Backtrace 插件(可选择性移除 Test::Unit 回溯中的行),2.3 在核心实现了 ActiveSupport::BacktraceCleaner 与 Rails::BacktraceCleaner。它同时支持过滤器(filter,对回溯行做正则替换)与静默器(silencer,整行删除)。新应用中 Rails 会自动加入一组静默器以消除最常见噪音,并生成 config/backtrace_silencers.rb 文件供你追加自定义项;该特性还让任意 gem 在回溯中都能更漂亮地打印。
开发模式下更快的启动:懒加载/自动加载
大量工作确保了 Rails(及其依赖)的部件只在真正需要时才进入内存。核心框架——Active Support、Active Record、Action Controller、Action Mailer 与 Action View——现在使用 autoload 惰性加载各自的类,有助于压低内存占用并提升整体性能。
新增 preload_frameworks 选项可控制核心库是否在启动时全部自动加载,默认 false(Rails 按片段自加载);但有些场景仍需一次性载入全部——Passenger 与 JRuby 都要求看到整体加载的 Rails。
rake gem 任务重写
各 rake gem 任务内部被大幅重构:系统现在能区分开发依赖与运行期依赖,解包系统更健壮,查询 gem 状态时信息更清晰,冷启动时更少遇到“鸡生蛋”依赖问题;还修复了 JRuby 下 gem 命令的问题,以及依赖试图引入已 vendored 的外部 gem 副本的问题。
其他 Railties 变化
- 更新并扩充了 CI 服务器构建 Rails 的说明。
- Rails 内部测试从
Test::Unit::TestCase切换到ActiveSupport::TestCase,Rails 核心测试需要 Mocha。 - 默认的
environment.rb被清理精简。 - dbconsole 脚本现在支持全数字密码而不崩溃。
Rails.root现在返回Pathname对象,可直接配合join方法使用,简化原先用File.join的代码。- 处理 CGI/FCGI 分发的若干 public 文件默认不再为每个应用生成;需要时可加
--with-dispatchers运行rails命令,或事后用rake rails:update:generate_dispatchers补上。 - Rails Guides 从 AsciiDoc 转换为 Textile 标记(本仓库的
guides/目录即是这一文档体系的延续)。 - Scaffold 生成的视图与控制器略有清理。
script/server新增--path参数,可从特定路径挂载 Rails 应用。- 若配置中的 gem 有缺失,gem rake 任务会跳过加载大部分环境,缓解“缺少 gem 导致 rake gems:install 无法运行”的鸡生蛋问题。
- gem 只会被解包一次,修复了以只读权限打包文件(如 hoe)导致的 gem 问题。
八、弃用清单
本版本弃用(或移除)了若干旧代码,迁移时需要留意:
- 依赖 inspector、reaper、spawner 脚本部署的开发者需注意:这些脚本不再包含在核心 Rails 中,需要时可从 irs_process_scripts 插件获取副本。
render_component从“弃用”变成“不存在”。仍需要它的话,安装 render_component 插件。- Rails 组件(components)的支持被移除。
script/performance/request从核心移除;可安装 request_profiler 插件获得完全相同的功能。ActionController::Base#session_enabled?弃用,因为会话已改为懒加载。protect_from_forgery的:digest与:secret选项弃用且无效。- 部分集成测试助手被移除:
response.headers["Status"]与headers["Status"]不再返回任何值(Rack 不允许返回头中出现 "Status"),但status与status_message助手仍可用;response.headers["cookie"]与headers["cookie"]不再返回 CGI cookie,可检查headers["Set-Cookie"]查看原始 cookie 头,或用cookies助手获取发给客户端的 cookie hash。 formatted_polymorphic_url弃用,改用带:format的polymorphic_url。ActionController::Response#set_cookie的:http_only选项更名为:httponly。to_sentence的:connector与:skip_last_comma选项被:words_connector、:two_words_connector、:last_word_connector取代。- 提交含空
file_field控件的 multipart 表单,旧行为是向控制器提交空字符串;由于 Rack multipart 解析器与旧 Rails 解析器的差异,现在提交 nil。
九、结语:2.3 的遗产在当前仓库中的映射
Rails 2.3 发布说明所确立的多项机制,在当前的 Rails 仓库中仍能找到清晰延续,这也印证了该版本的技术含金量:
- 批处理 API:
find_each/find_in_batches保留于 batches.rb,默认批大小仍为 1000,并扩展出start/finish/cursor/order等参数。 - 嵌套属性:
accepts_nested_attributes_for保留于 nested_attributes.rb,reject_if/allow_destroy选项语义与 2.3 一致。 - 嵌套事务:基于 savepoint 的
SavepointTransaction仍见诸 transaction.rb。 - HTTP Digest 认证:
authenticate_or_request_with_http_digest保留于 http_authentication.rb。 - 可替换 XML 解析器:
XmlMini.backend=保留并增强于 xml_mini.rb。 Object#try保留并扩展了try!,见 try.rb。
需要说明的是:本文档描述的是 Rails 2.3(2009 年发布)的行为与 API,其中动态/默认作用域、formatted_ 助手、CGI 处理器等细节在后继版本中已被替换或弃用。阅读时应以“理解演进脉络”为目的,具体使用请以目标版本的官方文档为准;而本文引用的当前仓库路径,仅用于展示 2.3 特性在现代代码库中的存续形态。
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