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 兼容的服务器。如果存在 rackup 配置文件,script/server也会读取它。默认情况下,它将查找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 = { :key => 'foo', ...而不是config.action_controller.session = { :session_key => 'foo', ...。 - 使用
ParamsParser中间件预处理任何 XML、JSON 或 YAML 请求,以便在它之后可以使用任何Rack::Request对象正常读取它们。
1.2. 对 Rails Engines 的重新支持
在几个版本没有升级之后,Rails 2.3 为 Rails Engines(可以嵌入到其他应用程序中的 Rails 应用程序)提供了一些新功能。首先,Engine 中的路由文件现在会自动加载和重新加载,就像您的 routes.rb 文件一样(这也适用于其他插件中的路由文件)。其次,如果您的插件有一个 app 文件夹,那么 app/[models|controllers|helpers] 将自动添加到 Rails 加载路径。Engines 现在也支持添加视图路径,并且 Action Mailer 和 Action View 都将使用来自 Engines 和其他插件的视图。
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 现在在 find 上有一个 :having 选项(以及 has_many 和 has_and_belongs_to_many 关联),用于在分组查找中过滤记录。正如那些具有丰富 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 Controller 重命名
如果您是对 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
另一个变化是,框架现在在检查各种位置的 JavaScript 时使用 Mime::JS,使其能够干净地处理这些替代方案。
- 主要贡献者: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 现在可以根据您设置的区域提供本地化视图。例如,假设您有一个带有 show 动作的 Posts 控制器。默认情况下,这将渲染 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 项目中可用的翻译数组。
此外,您可以使用相同的方案来本地化 public 目录中的救援文件:例如,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 处理已稍作清理:当响应没有主体或通过
send_file发送文件时,Rails 现在将跳过发送 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 %>
- 主要贡献者:Eloy Duran
- 更多信息
6.2. 智能渲染局部模板
多年来,渲染方法变得越来越智能,现在它甚至更智能了。如果您有一个对象或集合以及一个合适的局部模板,并且命名匹配,您现在可以直接渲染该对象,事情就会正常工作。例如,在 Rails 2.3 中,这些渲染调用将在您的视图中工作(假设命名合理):
# 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. 将资产主机作为对象
Edge 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助手已重构,使其更简洁直观。- 即使 URL 中有多个查询参数,
current_page?现在也能正常工作。
7. Active Support
Active Support 有一些有趣的更改,包括引入 Object#try。
7.1. Object#try
很多人都采用了使用 try() 来尝试对对象进行操作的观念。这在视图中特别有用,您可以避免 nil 检查,通过编写类似 <%= @person.try(:name) %> 的代码。现在,它已直接内置到 Rails 中。在 Rails 中实现时,它会在私有方法上引发 NoMethodError,并且如果对象为 nil,则始终返回 nil。
- 更多信息:try()
7.2. Object#tap 反向移植
Object#tap 是 Ruby 1.9 和 1.8.7 的一个补充,它类似于 Rails 长期以来拥有的 returning 方法:它会执行一个块,然后返回被执行的对象。Rails 现在也包含了代码,使其在旧版本的 Ruby 中可用。
7.3. XMLmini 可替换解析器
通过允许您插入不同的解析器,Active Support 中对 XML 解析的支持变得更加灵活。默认情况下,它使用标准的 REXML 实现,但只要您安装了适当的 gems,您就可以轻松地为自己的应用程序指定更快的 LibXML 或 Nokogiri 实现:
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 指南已从 AsciiDoc 转换为 Textile 标记。
- Scaffolded 视图和控制器已稍作清理。
script/server现在接受--path参数,以便从特定路径挂载 Rails 应用程序。- 如果任何配置的 gems 缺失,gem rake 任务将跳过加载大部分环境。这应该解决了许多“鸡生蛋”问题,即 rake gems:install 无法运行,因为 gems 缺失。
- Gems 现在只解包一次。这修复了 gems(例如 hoe)的文件权限为只读的问题。
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 编译。