1 基础设施
Rails 2.2 对保持 Rails 运行和与世界其他部分连接的基础设施进行了重要的更新。
1.1 国际化
Rails 2.2 提供了一个简单的国际化系统(或者对于那些厌倦了打字的人来说,叫做 i18n)。
- 主要贡献者:Rails i18 团队
- 更多信息:
1.2 与 Ruby 1.9 和 JRuby 的兼容性
除了线程安全性,还进行了大量工作,使得 Rails 在 JRuby 和即将发布的 Ruby 1.9 上能够良好运行。由于 Ruby 1.9 是一个不断变化的目标,运行最新版的 Rails 在最新版的 Ruby 上仍然是一个试错的过程,但是当后者发布时,Rails 已经准备好过渡到 Ruby 1.9。
2 文档
Rails 的内部文档,以代码注释的形式,在许多地方得到了改进。此外,Ruby on Rails Guides 项目是关于主要 Rails 组件信息的权威来源。在其首次正式发布中,Guides 页面包括:
- Rails 入门指南
- Rails 数据库迁移
- Active Record 关联
- Active Record 查询接口
- Rails 中的布局和渲染
- Action View 表单助手
- 从外部了解 Rails 路由
- Action Controller 概述
- Rails 缓存
- Rails 应用程序测试指南
- 保护 Rails 应用程序
- 调试 Rails 应用程序
- 创建 Rails 插件的基础知识
总的来说,这些指南为初学者和中级 Rails 开发人员提供了数以万计的指导词。
如果你想在应用程序内部生成这些指南:
$ rake doc:guides
这将把指南放在 Rails.root/doc/guides
中,你可以通过在你喜欢的浏览器中打开 Rails.root/doc/guides/index.html
来开始浏览。
- 主要贡献者:Xavier Noria 和 Hongli Lai
- 更多信息:
3 更好地与 HTTP 集成:开箱即用的 ETag 支持
支持在 HTTP 标头中使用 ETag 和上次修改时间戳意味着如果 Rails 收到一个对最近未修改的资源的请求,它现在可以发送一个空响应。这使得你可以检查是否需要发送响应。
class ArticlesController < ApplicationController
def show_with_respond_to_block
@article = Article.find(params[:id])
# 如果请求发送的标头与 stale? 方法提供的选项不同,那么请求确实是过期的,respond_to 块将被触发(并且 stale? 调用的选项将设置在响应中)。
#
# 如果请求标头匹配,那么请求是新鲜的,respond_to 块不会被触发。相反,将发生默认渲染,它将检查上次修改和 ETag 标头,并得出只需要发送 "304 Not Modified" 而不是渲染模板。
if stale?(:last_modified => @article.published_at.utc, :etag => @article)
respond_to do |wants|
# 正常的响应处理
end
end
end
def show_with_implied_render
@article = Article.find(params[:id])
# 设置响应标头并将其与请求进行比较,如果请求是过期的(即 etag 或 last-modified 没有匹配),那么默认渲染模板将发生。
# 如果请求是新鲜的,那么默认渲染将返回 "304 Not Modified" 而不是渲染模板。
fresh_when(:last_modified => @article.published_at.utc, :etag => @article)
end
end
4 线程安全性
使 Rails 线程安全的工作正在 Rails 2.2 中推出。根据你的 Web 服务器基础设施,这意味着你可以处理更多请求,使用更少的 Rails 副本在内存中,从而提高服务器性能并更好地利用多个核心。
要在应用程序的生产模式中启用多线程调度,请在config/environments/production.rb
中添加以下行:
config.threadsafe!
- 更多信息:
5 Active Record
这里有两个重要的新增功能需要讨论:事务性迁移和数据库连接池事务。还有一种更清晰的语法用于连接表条件,以及许多较小的改进。
5.1 事务性迁移
历史上,多步骤的Rails迁移一直是一个麻烦的问题。如果在迁移过程中出现问题,错误之前的所有更改都会改变数据库,错误之后的所有更改都不会应用。此外,迁移版本被存储为已执行,这意味着在修复问题后无法简单地通过rake db:migrate:redo
重新运行迁移。事务性迁移通过将迁移步骤包装在DDL事务中来改变这一点,因此如果任何步骤失败,整个迁移都会被撤消。在Rails 2.2中,事务性迁移在PostgreSQL上得到了支持。该代码将来可以扩展到其他数据库类型,并且IBM已经扩展它以支持DB2适配器。
5.2 连接池
连接池允许Rails在一个数据库连接池中分发数据库请求,该连接池将增长到最大大小(默认为5,但您可以在database.yml
中添加一个pool
键来调整此值)。这有助于消除支持许多并发用户的应用程序中的瓶颈。还有一个wait_timeout
,默认为5秒。如果需要,ActiveRecord::Base.connection_pool
可以直接访问连接池。
development:
adapter: mysql
username: root
database: sample_development
pool: 10
wait_timeout: 10
5.3 连接表条件的哈希
现在可以使用哈希指定连接表的条件。如果需要在复杂的连接中查询,这将非常有帮助。
class Photo < ActiveRecord::Base
belongs_to :product
end
class Product < ActiveRecord::Base
has_many :photos
end
# 获取所有具有无版权照片的产品:
Product.all(:joins => :photos, :conditions => { :photos => { :copyright => false }})
5.4 新的动态查找器
Active Record的动态查找器系列中添加了两组新方法。
5.4.1 find_last_by_attribute
find_last_by_attribute
方法等同于Model.last(:conditions => {:attribute => value})
# 获取最后一个来自伦敦注册的用户
User.find_last_by_city('London')
- 主要贡献者:Emilio Tagua
5.4.2 find_by_attribute!
find_by_attribute!
的新版本是Model.first(:conditions => {:attribute => value}) || raise ActiveRecord::RecordNotFound
。如果找不到匹配的记录,这个方法不会返回nil
,而是会引发异常。
# 如果'Moby'尚未注册,则引发ActiveRecord::RecordNotFound异常!
User.find_by_name!('Moby')
- 主要贡献者:Josh Susser
5.5 关联关系尊重私有/受保护范围
Active Record关联代理现在尊重代理对象上方法的范围。以前(假设User has_one :account),@user.account.private_method
会调用关联的Account对象上的私有方法。在Rails 2.2中,这将失败;如果您需要此功能,应该使用@user.account.send(:private_method)
(或将方法从私有或受保护更改为公共)。请注意,如果您覆盖了method_missing
,您还应该覆盖respond_to
以匹配行为,以使关联正常工作。
- 主要贡献者:Adam Milligan
- 更多信息:
5.6 其他Active Record更改
rake db:migrate:redo
现在接受一个可选的VERSION,以将特定迁移目标重新执行- 设置
config.active_record.timestamped_migrations = false
,以便迁移具有数字前缀而不是UTC时间戳。 - 计数缓存列(对于使用
counter_cache => true
声明的关联)不再需要初始化为零。 ActiveRecord::Base.human_name
用于对模型名称进行国际化感知的人性化翻译
6 Action Controller
在控制器方面,有几个变化可以帮助整理您的路由。路由引擎中还有一些内部变化,以降低复杂应用程序的内存使用。
6.1 浅层嵌套路由
浅层嵌套路由提供了解决使用深层嵌套资源的难题的方法。使用浅层嵌套,您只需要提供足够的信息来唯一标识您想要处理的资源。
map.resources :publishers, :shallow => true do |publisher|
publisher.resources :magazines do |magazine|
magazine.resources :photos
end
end
这将使得以下路由可以被识别:
/publishers/1 ==> publisher_path(1)
/publishers/1/magazines ==> publisher_magazines_path(1)
/magazines/2 ==> magazine_path(2)
/magazines/2/photos ==> magazines_photos_path(2)
/photos/3 ==> photo_path(3)
- 主要贡献者:S. Brent Faulkner
- 更多信息:
6.2 成员或集合路由的方法数组
现在,您可以为新的成员或集合路由提供一个方法数组。这样,当您需要处理多个动词时,您不再需要将路由定义为接受任何动词。在Rails 2.2中,这是一个合法的路由声明:
map.resources :photos, :collection => { :search => [:get, :post] }
- 主要贡献者:Brennan Dunn
6.3 具有特定动作的资源
默认情况下,当您使用map.resources
创建路由时,Rails会为七个默认动作(index、show、create、new、edit、update和destroy)生成路由。但是,每个路由在应用程序中占用内存,并导致Rails生成额外的路由逻辑。现在,您可以使用:only
和:except
选项来精确控制Rails为资源生成的路由。您可以提供单个动作、动作数组或特殊的:all
或:none
选项。这些选项会被嵌套资源继承。
map.resources :photos, :only => [:index, :show]
map.resources :products, :except => :destroy
- 主要贡献者:Tom Stuart
6.4 其他动作控制器的变化
- 现在,您可以轻松地为路由请求时引发的异常显示自定义错误页面。
- 默认情况下,禁用了HTTP Accept头。您应该优先使用格式化的URL(例如
/customers/1.xml
)来指示您想要的格式。如果您需要Accept头,可以使用config.action_controller.use_accept_header = true
将其打开。 - 基准测试的数字现在以毫秒为单位报告,而不是秒的小小部分。
- Rails现在支持仅HTTP的Cookie(并将其用于会话),这有助于减轻新版本浏览器中的一些跨站脚本风险。
redirect_to
现在完全支持URI方案(因此,例如,您可以重定向到svn`ssh: URI)。render
现在支持:js
选项,以使用正确的MIME类型呈现纯粹的JavaScript。- 请求伪造保护现在仅适用于HTML格式的内容请求。
- 如果传递的参数为nil,多态URL将更加合理。例如,使用nil日期调用
polymorphic_path([@project, @date, @area])
将给出project_area_path
。
7 Action View
javascript_include_tag
和stylesheet_link_tag
支持一个新的:recursive
选项,与:all
一起使用,以便您可以使用一行代码加载整个文件树。- 包含的Prototype JavaScript库已升级到1.6.0.3版本。
RJS#page.reload
通过JavaScript重新加载浏览器的当前位置atom_feed
助手现在接受一个:instruct
选项,让您插入XML处理指令。
8 Action Mailer
Action Mailer现在支持邮件布局。您可以通过提供一个适当命名的布局(例如,CustomerMailer
类希望使用layouts/customer_mailer.html.erb
)使您的HTML邮件与浏览器视图一样漂亮。
- 更多信息:
Action Mailer现在通过自动启用STARTTLS来支持GMail的SMTP服务器。这需要安装Ruby 1.8.7。
9 Active Support
Active Support现在为Rails应用程序提供了内置的记忆化、each_with_object
方法、委托的前缀支持和其他各种新的实用方法。
9.1 记忆化
记忆化是一种模式,它初始化一个方法一次,然后将其值存储起来以供重复使用。您可能在自己的应用程序中使用过这种模式:
def full_name
@full_name ||= "#{first_name} #{last_name}"
end
记忆化使您可以以声明性的方式处理此任务:
extend ActiveSupport::Memoizable
def full_name
"#{first_name} #{last_name}"
end
memoize :full_name
记忆化的其他特性包括unmemoize
、unmemoize_all
和memoize_all
,用于打开或关闭记忆化。
* 主要贡献者:Josh Peek
* 更多信息:
* Edge Rails的新功能:简单的记忆化
* 记忆化指南
9.2 each_with_object
each_with_object
方法提供了一个替代inject
的方法,使用了从Ruby 1.9中回溯的方法。它遍历一个集合,将当前元素和记忆传递给块。
%w(foo bar).each_with_object({}) { |str, hsh| hsh[str] = str.upcase } # => {'foo' => 'FOO', 'bar' => 'BAR'}
主要贡献者:Adam Keys
9.3 带前缀的委托
如果你从一个类委托行为到另一个类,现在你可以指定一个前缀来标识被委托的方法。例如:
class Vendor < ActiveRecord::Base
has_one :account
delegate :email, :password, :to => :account, :prefix => true
end
这将生成委托方法vendor#account_email
和vendor#account_password
。你也可以指定一个自定义前缀:
class Vendor < ActiveRecord::Base
has_one :account
delegate :email, :password, :to => :account, :prefix => :owner
end
这将生成委托方法vendor#owner_email
和vendor#owner_password
。
主要贡献者:Daniel Schierbeck
9.4 其他Active Support的变化
- 对
ActiveSupport::Multibyte
进行了广泛更新,包括Ruby 1.9的兼容性修复。 - 添加了
ActiveSupport::Rescuable
,允许任何类混入rescue_from
语法。 Date
和Time
类的past?
、today?
和future?
方法,用于方便地进行日期/时间比较。Array#second
到Array#fifth
作为Array#[1]
到Array#[4]
的别名Enumerable#many?
用于封装collection.size > 1
Inflector#parameterize
生成一个URL可用的版本,用于to_param
。Time#advance
可以识别小数天和周,所以你可以使用1.7.weeks.ago
、1.5.hours.since
等等。- 包含的TzInfo库已升级到0.3.12版本。
ActiveSupport::StringInquirer
提供了一种漂亮的方式来测试字符串的相等性:ActiveSupport::StringInquirer.new("abc").abc? => true
10 Railties
在Railties(Rails核心代码)中,最大的变化在于config.gems
机制。
10.1 config.gems
为了避免部署问题并使Rails应用程序更加自包含,可以将Rails应用程序所需的所有gem的副本放在/vendor/gems
中。这个功能首次出现在Rails 2.1中,但在Rails 2.2中更加灵活和健壮,处理了gem之间的复杂依赖关系。Rails中的gem管理包括以下命令:
- 在
config/environment.rb
文件中使用config.gem _gem_name_
- 使用
rake gems
列出所有配置的gem,以及它们(和它们的依赖项)是否已安装、冻结或框架(框架gem是在执行gem依赖代码之前由Rails加载的gem;这样的gem不能被冻结) - 使用
rake gems:install
将缺失的gem安装到计算机上 - 使用
rake gems:unpack
将所需的gem的副本放置在/vendor/gems
中 - 使用
rake gems:unpack:dependencies
将所需的gem及其依赖项的副本放置在/vendor/gems
中 - 使用
rake gems:build
构建任何缺失的本地扩展 - 使用
rake gems:refresh_specs
将使用Rails 2.1创建的vendored gem与Rails 2.2的存储方式保持一致
可以通过在命令行上指定GEM=_gem_name_
来解压或安装单个gem。
10.2 其他Railties的变化
- 如果你是Thin web服务器的粉丝,你会很高兴知道
script/server
现在直接支持Thin。 script/plugin install <plugin> -r <revision>
现在可以与基于git和svn的插件一起使用。script/console
现在支持--debugger
选项- 在Rails源码中包含了设置连续集成服务器来构建Rails本身的说明
rake notes:custom ANNOTATION=MYFLAG
允许你列出自定义注释。- 将
Rails.env
封装在StringInquirer
中,这样你就可以使用Rails.env.development?
- 为了消除弃用警告并正确处理gem依赖关系,Rails现在需要rubygems 1.3.1或更高版本。
11 已弃用
在这个版本中,一些旧代码已被弃用:
Rails::SecretKeyGenerator
已被ActiveSupport::SecureRandom
取代render_component
已被弃用。如果你需要这个功能,可以使用render_components插件。渲染局部视图时的隐式局部变量赋值已被弃用。
def partial_with_implicit_local_assignment @customer = Customer.new("Marcel") render :partial => "customer" end
以前的代码在局部视图'customer'中提供了一个名为
customer
的局部变量。现在你应该通过:locals
哈希显式传递所有变量。country_select
已被移除。请查看弃用页面获取更多信息和插件替代方案。ActiveRecord::Base.allow_concurrency
不再起作用。ActiveRecord::Errors.default_error_messages
已被弃用,推荐使用I18n.translate('activerecord.errors.messages')
。国际化的
%s
和%d
插值语法已被弃用。String#chars
已被弃用,推荐使用String#mb_chars
。弃用了小数月份或小数年份的持续时间。请使用 Ruby 的核心
Date
和Time
类进行计算。Request#relative_url_root
已被弃用。请使用ActionController::Base.relative_url_root
代替。
12 致谢
发布说明由 Mike Gunderloy 编写
反馈
欢迎您帮助改进本指南的质量。
如果您发现任何拼写错误或事实错误,请贡献您的意见。 要开始,请阅读我们的 文档贡献 部分。
您还可能会发现不完整的内容或过时的内容。 请为主要内容添加任何缺失的文档。请先检查 Edge 指南,以验证问题是否已经修复或尚未修复。 请参阅 Ruby on Rails 指南准则 以了解样式和规范。
如果您发现需要修复但无法自行修复的问题,请 提交问题。
最后但同样重要的是,欢迎您在 官方 Ruby on Rails 论坛 上讨论有关 Ruby on Rails 文档的任何问题。