1 应用程序架构
Rails 应用程序的架构有两个主要变化:完全集成 Rack 模块化 Web 服务器接口,以及更新后的 Rails Engines 支持。
1.1 Rack 集成
Rails 现在已经告别了 CGI 时代,并在所有地方都使用 Rack。这需要并导致了许多内部更改(但如果您使用 CGI,请不要担心;Rails 现在通过代理接口支持 CGI)。尽管如此,这仍然是 Rails 内部结构的重大变化。升级到 2.3 后,您应该在本地环境和生产环境中进行测试。一些需要测试的内容
- 会话
- Cookie
- 文件上传
- JSON/XML API
以下是与 Rack 相关的更改摘要
script/server
已切换为使用 Rack,这意味着它支持任何兼容 Rack 的服务器。script/server
也会在存在的情况下拾取 rackup 配置文件。默认情况下,它会查找config.ru
文件,但您可以使用-c
开关覆盖它。- FCGI 处理程序通过 Rack 进行。
ActionController::Dispatcher
维持自己的默认中间件栈。中间件可以被注入、重新排序和移除。栈在启动时被编译成一个链。您可以在environment.rb
中配置中间件栈。- 已添加
rake middleware
任务以检查中间件栈。这对于调试中间件栈的顺序很有用。 - 集成测试运行程序已修改为执行整个中间件和应用程序栈。这使得集成测试非常适合测试 Rack 中间件。
ActionController::CGIHandler
是围绕 Rack 的向后兼容 CGI 包装器。CGIHandler
用于接收旧的 CGI 对象并将它的环境信息转换为 Rack 兼容的格式。CgiRequest
和CgiResponse
已被移除。- 会话存储现在是延迟加载的。如果您在请求过程中从未访问过会话对象,它将永远不会尝试加载会话数据(解析 Cookie,从 Memcache 加载数据或查找 Active Record 对象)。
- 您不再需要在测试中使用
CGI::Cookie.new
来设置 Cookie 值。现在,将String
值分配给 request.cookies["foo"] 将按预期设置 Cookie。 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
中间件会自动插入中间件栈中。此中间件设置并刷新每个请求的 Active Record 查询缓存。 - Rails 路由器和控制器类遵循 Rack 规范。您可以使用
SomeController.call(env)
直接调用控制器。路由器将路由参数存储在rack.routing_args
中。 ActionController::Request
继承自Rack::Request
。- 请不要使用
config.action_controller.session = { :session_key => 'foo', ...
,而应使用config.action_controller.session = { :key => 'foo', ...
。 - 使用
ParamsParser
中间件预处理任何 XML、JSON 或 YAML 请求,以便它们在之后可以正常读取任何Rack::Request
对象。
1.2 更新后的 Rails Engines 支持
在几个版本没有升级之后,Rails 2.3 提供了 Rails Engines(可以嵌入在其他应用程序中的 Rails 应用程序)的一些新功能。首先,引擎中的路由文件现在会自动加载和重新加载,就像您的 routes.rb
文件一样(这也适用于其他插件中的路由文件)。其次,如果您的插件有一个 app 文件夹,那么 app/[models|controllers|helpers] 会自动添加到 Rails 加载路径中。引擎现在还支持添加视图路径,Action Mailer 和 Action View 将使用来自引擎和其他插件的视图。
2 文档
《Ruby on Rails 指南》项目发布了多个针对 Rails 2.3 的额外指南。此外,一个单独的网站维护着 Edge Rails 指南的更新版本。其他文档工作包括重新发布Rails Wiki,以及早期规划 Rails 书籍。
- 更多信息:Rails 文档项目
3 Ruby 1.9.1 支持
无论您是在 Ruby 1.8 还是现在已发布的 Ruby 1.9.1 上运行,Rails 2.3 都应该通过其所有测试。不过,您应该注意,迁移到 1.9.1 需要检查您所依赖的所有数据适配器、插件和其他代码以确保其与 Ruby 1.9.1 兼容,以及 Rails 核心本身。
4 Active Record
Active Record 在 Rails 2.3 中获得了大量的新功能和错误修复。主要亮点包括嵌套属性、嵌套事务、动态范围和默认范围,以及批量处理。
4.1 嵌套属性
Active Record 现在可以更新嵌套模型中的属性,前提是您告诉它这样做。
class Book < ActiveRecord::Base
has_one :author
has_many :pages
accepts_nested_attributes_for :author, :pages
end
启用嵌套属性可以实现许多功能:自动(原子)保存记录及其关联的子记录,子记录感知验证,以及嵌套表单的支持(稍后讨论)。
您还可以使用 :reject_if
选项指定对通过嵌套属性添加的任何新记录的要求。
accepts_nested_attributes_for :author,
:reject_if => proc { |attributes| attributes['name'].blank? }
- 主要贡献者:Eloy Duran
- 更多信息:嵌套模型表单
4.2 嵌套事务
Active Record 现在支持嵌套事务,这是一个备受期待的功能。现在您可以像这样编写代码。
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) # => Returns only Admin
嵌套事务允许您回滚内部事务,而不会影响外部事务的状态。如果您希望事务嵌套,则必须显式添加 :requires_new
选项;否则,嵌套事务将仅仅成为父事务的一部分(就像它目前在 Rails 2.2 中的行为一样)。在底层,嵌套事务使用保存点,因此即使在不支持真正的嵌套事务的数据库上也能得到支持。还有一些魔术方法可以使这些事务在测试期间与事务性夹具很好地配合。
- 主要贡献者:Jonathan Viney 和 Hongli Lai
4.3 动态范围
您了解 Rails 中的动态查找器(它允许您动态地创建 find_by_color_and_flavor
等方法)和命名范围(它允许您将可重复使用的查询条件封装到友好的名称中,例如 currently_active
)。现在,您可以使用动态范围方法。这个想法是将语法整合在一起,允许动态过滤以及方法链式调用。例如
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")
使用动态范围无需定义任何内容:它们只是起作用。
- 主要贡献者:Yaroslav Markin
- 更多信息:Edge Rails 中的新功能:动态范围方法
4.4 默认范围
Rails 2.3 将引入默认范围的概念,类似于命名范围,但应用于模型中的所有命名范围或查找方法。例如,您可以编写 default_scope :order => 'name ASC'
,这样每次您从该模型中检索记录时,它们都会按名称排序(除非您覆盖了该选项,当然)。
- 主要贡献者:Paweł Kondzior
- 更多信息:Edge Rails 中的新功能:默认范围
4.5 批量处理
现在,您可以使用 find_in_batches
从 Active Record 模型中处理大量记录,而对内存的压力更小。
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 个),您应该只使用带有您自己的循环的常规查找方法。
- 更多信息(在那个时候,便利方法被称为
each
)。
4.6 回调的多个条件
在使用 Active Record 回调时,您现在可以在同一个回调上组合 :if
和 :unless
选项,并将多个条件作为数组提供。
before_save :update_credit_rating, :if => :active,
:unless => [:admin, :cash_only]
- 主要贡献者:L. Caviola
4.7 带有 having 的查找
Rails 现在在查找(以及 has_many
和 has_and_belongs_to_many
关联)中有一个 :having
选项,用于过滤分组查找中的记录。正如那些具有丰富 SQL 背景的人所知,这允许根据分组结果进行过滤。
developers = Developer.find(:all, :group => "salary",
:having => "sum(salary) > 10000", :select => "salary")
- 主要贡献者:Emilio Tagua
4.8 重新连接 MySQL 连接
MySQL 在其连接中支持一个重新连接标志 - 如果设置为 true,那么客户端将在连接丢失的情况下尝试重新连接到服务器,然后再放弃。您现在可以在 database.yml
中为您的 MySQL 连接设置 reconnect = true
,以便从 Rails 应用程序获得此行为。默认值为 false
,因此现有应用程序的行为不会改变。
- 主要贡献者:Dov Murik
- 更多信息
4.9 其他 Active Record 更改
- 从为
has_and_belongs_to_many
预加载生成的 SQL 中删除了额外的AS
,使其更适合某些数据库。 ActiveRecord::Base#new_record?
现在在遇到现有记录时返回false
而不是nil
。- 修复了在某些
has_many :through
关联中引号化表名的错误。 - 您现在可以为
updated_at
时间戳指定特定的时间戳:cust = Customer.create(:name => "ABC Industries", :updated_at => 1.day.ago)
- 在
find_by_attribute!
调用失败时提供更好的错误消息。 - Active Record 的
to_xml
支持通过添加:camelize
选项变得更加灵活。 - 修复了从
before_update
或before_create
中取消回调的错误。 - 添加了通过 JDBC 测试数据库的 Rake 任务。
validates_length_of
将使用自定义错误消息,带有:in
或:within
选项(如果提供了)。- 作用域选择上的计数现在可以正常工作,因此您可以执行诸如
Account.scoped(:select => "DISTINCT credit_limit").count
之类操作。 ActiveRecord::Base#invalid?
现在与ActiveRecord::Base#valid?
相反。
5 Action Controller
Action Controller 在此版本中对渲染进行了一些重大更改,以及在路由和其他领域方面的改进。
5.1 统一渲染
ActionController::Base#render
在决定渲染内容方面变得更加智能。现在,您只需告诉它要渲染什么,并期望获得正确的结果。在旧版本的 Rails 中,您经常需要提供显式信息来渲染。
render :file => '/tmp/random_file.erb'
render :template => 'other_controller/action'
render :action => 'show'
现在在 Rails 2.3 中,您只需提供要渲染的内容即可。
render '/tmp/random_file.erb'
render 'other_controller/action'
render 'show'
render :show
Rails 根据要渲染的内容中是否存在前导斜杠、嵌入式斜杠或根本没有斜杠,在文件、模板和操作之间进行选择。请注意,您也可以在渲染操作时使用符号而不是字符串。其他渲染样式(:inline
、:text
、:update
、:nothing
、:json
、:xml
、:js
)仍然需要显式选项。
5.2 应用程序控制器已重命名
如果您是那些一直被 application.rb
的特殊命名方式困扰的人之一,那么欢呼吧!它在 Rails 2.3 中被重构为 application_controller.rb
。此外,还有一个新的 rake 任务 rake rails:update:application_controller
可以自动为您执行此操作 - 并且它将在正常的 rake rails:update
过程中运行。
5.3 HTTP 摘要身份验证支持
Rails 现在内置了对 HTTP 摘要身份验证的支持。要使用它,您可以调用 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
- 主要贡献者:Gregg Kellogg
- 更多信息:Edge Rails 中的新功能:HTTP 摘要身份验证
5.4 更高效的路由
Rails 2.3 中有一些重大的路由更改。formatted_
路由助手已不再使用,取而代之的是将 :format
作为选项传递。这将任何资源的路由生成过程减少了 50% - 并可以节省大量的内存(在大型应用程序上可节省高达 100MB)。如果您的代码使用 formatted_
助手,它暂时仍然可以工作 - 但是该行为已弃用,如果您使用新的标准重写这些路由,那么您的应用程序将更加高效。另一个重大变化是 Rails 现在支持多个路由文件,而不仅仅是 routes.rb
。您可以使用 RouteSet#add_configuration_file
在任何时候引入更多路由 - 而不必清除当前已加载的路由。虽然此更改对于 Engines 来说最有用,但您可以在任何需要分批加载路由的应用程序中使用它。
- 主要贡献者:Aaron Batalion
5.5 基于 Rack 的延迟加载会话
Action Controller 会话存储的底层机制发生了重大改变,转移到了 Rack 级别。这涉及代码的相当多的工作,但对于您的 Rails 应用程序来说应该是完全透明的(作为奖励,一些围绕旧 CGI 会话处理程序的令人讨厌的补丁已被删除)。不过,这仍然很重要,原因很简单:非 Rails Rack 应用程序可以访问与您的 Rails 应用程序相同的会话存储处理程序(因此是相同的会话)。此外,会话现在是延迟加载的(与框架其他部分的加载改进一致)。这意味着您不再需要显式禁用会话,如果您不想要它们;只需不引用它们,它们就不会加载。
5.6 MIME 类型处理更改
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
另一个变化是,框架现在在各种位置使用 Mime::JS
来检查 JavaScript,从而使其能够干净地处理这些备选方案。
- 主要贡献者:Seth Fitzsimmons
5.7 respond_to
的优化
在 Rails-Merb 团队合并的最初成果中,Rails 2.3 包含了一些针对 respond_to
方法的优化,该方法当然在许多 Rails 应用程序中被大量使用,以允许您的控制器根据传入请求的 MIME 类型以不同的格式格式化结果。在消除对 method_missing
的调用以及一些分析和调整之后,我们发现使用简单的 respond_to
在三种格式之间切换的每秒请求数量提高了 8%。最好的部分?您的应用程序代码无需更改即可利用这种加速。
5.8 改进的缓存性能
Rails 现在为每个请求保留一个从远程缓存存储中读取的本地缓存,减少不必要的读取,从而提高网站性能。虽然这项工作最初仅限于 MemCacheStore
,但它可用于任何实现所需方法的远程存储。
- 主要贡献者:Nahum Wild
5.9 本地化视图
Rails 现在可以提供本地化视图,具体取决于您设置的语言环境。例如,假设您有一个 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
,它们返回当前 Rails 项目中可用翻译的数组。
此外,您可以使用相同的方案来本地化公共目录中的 rescue 文件:例如,public/500.da.html
或 public/404.en.html
可以工作。
5.10 翻译的部分作用域
对翻译 API 的更改使在部分中编写关键翻译变得更容易且重复性更低。如果您从 people/index.html.erb
模板调用 translate(".foo")
,您实际上将调用 I18n.translate("people.index.foo")
。如果您没有在键前面加上句点,则 API 不会像以前那样进行作用域。
5.11 其他 Action Controller 更改
- ETag 处理已稍微清理:Rails 现在将在没有响应主体时或使用
send_file
发送文件时跳过发送 ETag 标头。 - Rails 检查 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 成员路由正常协作。- 浅层路由现在可以正确地尊重命名空间。
polymorphic_url
在处理具有不规则复数名称的对象方面做得更好。
6 Action View
Rails 2.3 中的 Action View 包含嵌套模型表单、对 render
的改进、日期选择帮助程序更灵活的提示以及资产缓存的加速,等等。
6.1 嵌套对象表单
如果父模型接受子对象的嵌套属性(如 Active Record 部分中所述),您可以使用 form_for
和 field_for
创建嵌套表单。这些表单可以无限嵌套,允许您在一个视图上编辑复杂的对象层次结构,而无需过多的代码。例如,给定此模型
class Customer < ActiveRecord::Base
has_many :orders
accepts_nested_attributes_for :orders, :allow_destroy => true
end
您可以在 Rails 2.3 中编写此视图
<% form_for @customer do |customer_form| %>
<div>
<%= customer_form.label :name, 'Customer Name:' %>
<%= customer_form.text_field :name %>
</div>
<!-- Here we call fields_for on the customer_form builder instance.
The block is called for each member of the orders collection. -->
<% customer_form.fields_for :orders do |order_form| %>
<p>
<div>
<%= order_form.label :number, 'Order Number:' %>
<%= order_form.text_field :number %>
</div>
<!-- The allow_destroy option in the model enables deletion of
child records. -->
<% unless order_form.object.new_record? %>
<div>
<%= order_form.label :_delete, 'Remove:' %>
<%= order_form.checkbox :_delete %>
</div>
<% end %>
</p>
<% end %>
<%= customer_form.submit %>
<% end %>
6.2 部分的智能渲染
render 方法多年来一直在变得更加智能,现在它变得更加智能。如果您有一个对象或集合以及一个合适的局部,并且命名匹配,您现在只需渲染对象,一切都会正常工作。例如,在 Rails 2.3 中,这些 render 调用将在您的视图中工作(假设命名合理)
# Equivalent of render :partial => 'articles/_article',
# :object => @article
render @article
# Equivalent of render :partial => 'articles/_article',
# :collection => @articles
render @articles
6.3 日期选择帮助程序的提示
在 Rails 2.3 中,您可以为各种日期选择帮助程序(date_select
、time_select
和 datetime_select
)提供自定义提示,与集合选择帮助程序的方式相同。您可以提供提示字符串或各个提示字符串的哈希表,用于各种组件。您也可以将 :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'})
- 主要贡献者:Sam Oliver
6.4 AssetTag 时间戳缓存
您可能熟悉 Rails 将时间戳添加到静态资产路径以作为“缓存破坏器”的做法。这有助于确保当您在服务器上更改诸如图像和样式表之类的内容时,不会从用户的浏览器缓存中提供过时的副本。您现在可以使用 Action View 的 cache_asset_timestamps
配置选项修改此行为。如果您启用缓存,则 Rails 将在首次提供资产时计算一次时间戳,并保存该值。这意味着提供静态资产时的文件系统调用更少(更昂贵) - 但这也意味着您无法在服务器运行时修改任何资产,并希望客户端获取更改。
6.5 资产主机作为对象
资产主机在边缘 Rails 中变得更加灵活,它能够将资产主机声明为响应调用的特定对象。这允许您在资产托管中实现您需要的任何复杂逻辑。
6.6 grouped_options_for_select 帮助程序方法
Action View 已经有一堆帮助程序来帮助生成选择控件,但现在又多了一个:grouped_options_for_select
。它接受一个字符串数组或哈希表,并将它们转换为用 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>
6.7 表单选择帮助程序的禁用选项标签
表单选择帮助程序(例如 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?})
6.8 关于模板加载的说明
Rails 2.3 包含为任何特定环境启用或禁用缓存模板的功能。缓存模板可以为您提供速度提升,因为它们在渲染时不会检查新的模板文件 - 但这也意味着您无法在不重启服务器的情况下“动态”替换模板。
在大多数情况下,您希望在生产环境中启用模板缓存,您可以在 production.rb
文件中进行设置
config.action_view.cache_template_loading = true
此行将在新的 Rails 2.3 应用程序中默认为您生成。如果您从旧版本的 Rails 升级,Rails 默认会在生产和测试中缓存模板,但在开发中不会。
6.9 其他 Action View 更改
- 针对 CSRF 保护的令牌生成已简化;现在 Rails 使用由
ActiveSupport::SecureRandom
生成的简单随机字符串,而不是乱用会话 ID。 auto_link
现在可以正确地将选项(例如:target
和:class
)应用于生成的电子邮件链接。autolink
帮助程序已重构,使其变得更简洁、更直观。current_page?
现在即使 URL 中有多个查询参数也能正常工作。
7 Active Support
Active Support 有几个有趣的更改,包括引入了 Object#try
。
7.1 Object#try
许多人已经采用使用 try() 对对象尝试操作的概念。它在视图中特别有用,您可以在其中通过编写类似 <%= @person.try(:name) %>
的代码来避免空检查。现在,它直接嵌入到 Rails 中。如在 Rails 中实现的那样,它在私有方法上引发 NoMethodError
,如果对象为空,始终返回 nil
。
- 更多信息:try()
7.2 Object#tap 回退
Object#tap
是对 Ruby 1.9 和 1.8.7 的补充,类似于 Rails 一直拥有的 returning
方法:它会对一个块进行 yield,然后返回 yield 的对象。Rails 现在包含代码以使其在旧版本的 Ruby 中也可用。
7.3 可互换的 XMLmini 解析器
Active Support 中对 XML 解析的支持已变得更加灵活,允许您换入不同的解析器。默认情况下,它使用标准的 REXML 实现,但您可以轻松地为自己的应用程序指定更快的 LibXML 或 Nokogiri 实现,前提是您安装了相应的 gem
XmlMini.backend = 'LibXML'
- 主要贡献者:Bart ten Brinke
- 主要贡献者:Aaron Patterson
7.4 TimeWithZone 的小数秒
Time
和 TimeWithZone
类包含一个 xmlschema
方法,用于返回 XML 友好格式的字符串时间。从 Rails 2.3 开始,TimeWithZone
支持与 Time
相同的参数来指定返回字符串中秒的小数部分的位数。
Time.zone.now.xmlschema(6) # => "2009-01-16T13:00:06.13653Z"
- 主要贡献者:Nicholas Dainty
7.5 JSON 密钥引用
如果您查看 "json.org" 网站上的规范,您会发现 JSON 结构中的所有键都必须是字符串,并且必须用双引号引起来。从 Rails 2.3 开始,即使是数字键,我们也会正确处理。
7.6 其他 Active Support 更改
- 您可以使用
Enumerable#none?
来检查是否没有元素与提供的代码块匹配。 - 如果您使用 Active Support 委托,新的
:allow_nil
选项允许您在目标对象为 nil 时返回nil
,而不是抛出异常。 ActiveSupport::OrderedHash
:现在实现了each_key
和each_value
。ActiveSupport::MessageEncryptor
提供了一种简单的方法来加密信息,以便将其存储在不受信任的位置(如 cookie 中)。- Active Support 的
from_xml
不再依赖于 XmlSimple。相反,Rails 现在包含了自己的 XmlMini 实现,其中只包含它需要的功能。这使得 Rails 可以抛弃它一直捆绑的 XmlSimple 拷贝。 - 如果您对私有方法进行记忆化,结果现在将是私有的。
String#parameterize
接受一个可选的分隔符:"Quick Brown Fox".parameterize('_') => "quick_brown_fox"
。number_to_phone
现在接受 7 位电话号码。ActiveSupport::Json.decode
现在处理\u0000
样式的转义序列。
8 Railties
除了上面提到的 Rack 更改之外,Railties(Rails 核心代码本身)还包含许多重大更改,包括 Rails Metal、应用程序模板和安静的回溯。
8.1 Rails Metal
Rails Metal 是一种新的机制,可以在 Rails 应用程序中提供超快的端点。Metal 类绕过路由和 Action Controller,为您提供原始速度(当然是以 Action Controller 中的所有内容为代价)。这建立在所有最近的基础工作之上,使 Rails 成为一个具有暴露的中间件堆栈的 Rack 应用程序。Metal 端点可以从您的应用程序或插件加载。
- 更多信息
8.2 应用程序模板
Rails 2.3 集成了 Jeremy McAnally 的 rg 应用程序生成器。这意味着我们现在在 Rails 中内置了基于模板的应用程序生成;如果您有一组插件,您将其包含在每个应用程序中(以及许多其他用例),您只需设置一次模板,然后在运行 rails
命令时反复使用它。还有一个 rake 任务可以将模板应用于现有应用程序。
$ rake rails:template LOCATION=~/template.rb
这将把模板中的更改层叠到项目已包含的任何代码之上。
- 主要贡献者:Jeremy McAnally
- 更多信息:Rails 模板
8.3 安静的回溯
建立在 thoughtbot 的 Quiet Backtrace 插件的基础上,该插件允许您选择性地从 Test::Unit
回溯中删除行,Rails 2.3 在核心代码中实现了 ActiveSupport::BacktraceCleaner
和 Rails::BacktraceCleaner
。这支持过滤器(对回溯行执行基于正则表达式的替换)和抑制器(完全删除回溯行)。Rails 自动添加抑制器以消除新应用程序中最常见的噪音,并构建一个 config/backtrace_silencers.rb
文件来保存您自己的添加。此功能还支持从回溯中的任何 gem 进行更漂亮的打印。
8.4 使用延迟加载/自动加载在开发模式下更快的启动时间
为了确保 Rails(及其依赖项)的部分只在实际需要时才被加载到内存中,做了大量工作。核心框架——Active Support、Active Record、Action Controller、Action Mailer 和 Action View——现在使用 autoload
来延迟加载其各个类。这项工作应该有助于降低内存占用并提高整体 Rails 性能。
您还可以指定(使用新的 preload_frameworks
选项)是否应该在启动时自动加载核心库。这默认为 false
,因此 Rails 按部分自动加载自身,但有一些情况下您仍然需要一次性加载所有内容——Passenger 和 JRuby 都希望看到 Rails 被完整加载。
8.5 rake gem 任务重写
各种 rake gem
任务的内部结构已经过大幅度修改,以使系统能够更好地适用于各种情况。gem 系统现在知道开发依赖项和运行时依赖项之间的区别,具有更强大的解包系统,在查询 gem 状态时提供更详细的信息,并且在从头开始构建时,更不容易出现“鸡和蛋”的依赖项问题。还修复了在 JRuby 下使用 gem 命令以及尝试引入已捆绑的 gem 的外部副本的依赖项的问题。
- 主要贡献者:David Dollar
8.6 其他 Railties 更改
- 更新 CI 服务器以构建 Rails 的说明已更新并扩展。
- 内部 Rails 测试已从
Test::Unit::TestCase
切换到ActiveSupport::TestCase
,Rails 核心代码要求 Mocha 进行测试。 - 默认的
environment.rb
文件已清理。 - dbconsole 脚本现在允许您使用全数字密码,而不会崩溃。
Rails.root
现在返回一个Pathname
对象,这意味着您可以直接使用它与join
方法 清理使用File.join
的现有代码。- /public 中处理 CGI 和 FCGI 调度的各种文件不再默认在每个 Rails 应用程序中生成(如果您需要它们,您仍然可以通过在运行
rails
命令时添加--with-dispatchers
来获取它们,或者稍后使用rake rails:update:generate_dispatchers
来添加它们)。 - Rails Guides 已从 AsciiDoc 转换为 Textile 标记。
- 脚手架视图和控制器已略微清理。
script/server
现在接受一个--path
参数,用于从特定路径挂载 Rails 应用程序。- 如果任何配置的 gem 丢失,gem rake 任务将跳过加载大部分环境。这应该可以解决许多“鸡和蛋”问题,这些问题会导致 rake gems:install 无法运行,因为 gem 丢失了。
- gem 现在只解包一次。这修复了 gem(例如 hoe)的问题,这些 gem 随文件一起打包,但文件具有只读权限。
9 已弃用
此版本中弃用了一些旧代码。
- 如果您是那些(相当罕见)依赖于 inspector、reaper 和 spawner 脚本的 Rails 开发人员之一,您需要知道这些脚本不再包含在 Rails 核心代码中。如果您需要它们,您可以通过 irs_process_scripts 插件获取副本。
render_component
在 Rails 2.3 中从“已弃用”变为“不存在”。如果您仍然需要它,可以安装 render_component 插件。- 对 Rails 组件的支持已被删除。
- 如果您习惯于运行
script/performance/request
来查看基于集成测试的性能,您需要学习一个新的技巧:该脚本现在已从 Rails 核心代码中删除。您可以安装新的 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 的哈希表。 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
控件发布多部分表单以前会向控制器提交空字符串。现在它提交的是 nil,这是由于 Rack 的多部分解析器与旧的 Rails 解析器之间的差异。
10 致谢
发布说明由 Mike Gunderloy 编译。此版本的 Rails 2.3 发布说明是根据 Rails 2.3 的 RC2 编译的。