更多内容请访问 rubyonrails.org:

Ruby on Rails 2.2 版本说明

Rails 2.2 提供了一些新的和改进的功能。此列表涵盖了主要的升级,但不包括每个小的错误修复和更改。如果您想查看所有内容,请查看 GitHub 上主要 Rails 存储库中的 提交列表

与 Rails 一起,2.2 版本标志着 Ruby on Rails 指南 的发布,这是正在进行的 Rails 指南黑客马拉松 的第一个成果。本网站将提供有关 Rails 主要功能的高质量文档。

1 基础设施

Rails 2.2 是一个重要的版本,它为 Rails 的持续运行和与外部世界的连接提供了基础设施。

1.1 国际化

Rails 2.2 提供了一个方便的国际化系统(或 i18n,对于那些厌倦打字的人来说)。

1.2 与 Ruby 1.9 和 JRuby 的兼容性

除了线程安全性之外,还进行了大量工作来使 Rails 与 JRuby 和即将推出的 Ruby 1.9 良好配合。由于 Ruby 1.9 是一个不断变化的目标,在边缘 Ruby 上运行边缘 Rails 仍然是一个不确定的命题,但 Rails 准备在 Ruby 1.9 发布后进行过渡。

2 文档

Rails 的内部文档(以代码注释的形式)在许多地方都得到了改进。此外,Ruby on Rails 指南 项目是有关主要 Rails 组件信息的权威来源。在其第一个正式版本中,指南页面包含

总而言之,指南为初级和中级 Rails 开发人员提供了数万字的指导。

如果您想在本地(在您的应用程序中)生成这些指南

$ rake doc:guides

这将把指南放在 Rails.root/doc/guides 中,您可以通过在您喜欢的浏览器中打开 Rails.root/doc/guides/index.html 来开始浏览。

3 与 HTTP 的更好集成:开箱即用的 ETag 支持

支持 HTTP 标头中的 ETag 和上次修改时间戳意味着 Rails 现在可以在获取最近未修改的资源的请求时发回空响应。这允许您检查是否需要发送响应。

class ArticlesController < ApplicationController
  def show_with_respond_to_block
    @article = Article.find(params[:id])

    # If the request sends headers that differs from the options provided to stale?, then
    # the request is indeed stale and the respond_to block is triggered (and the options
    # to the stale? call is set on the response).
    #
    # If the request headers match, then the request is fresh and the respond_to block is
    # not triggered. Instead, the default render will occur, which will check the last-modified
    # and etag headers and conclude that it only needs to send a "304 Not Modified" instead
    # of rendering the template.
    if stale?(:last_modified => @article.published_at.utc, :etag => @article)
      respond_to do |wants|
        # normal response processing
      end
    end
  end

  def show_with_implied_render
    @article = Article.find(params[:id])

    # Sets the response headers and checks them against the request, if the request is stale
    # (i.e. no match of either etag or last-modified), then the default render of the template happens.
    # If the request is fresh, then the default render will return a "304 Not Modified"
    # instead of rendering the template.
    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

# Get all products with copyright-free photos:
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})

# Get the last user who signed up from London
User.find_last_by_city('London')

5.4.2 find_by_attribute!

find_by_attribute! 的新叹号版本等效于 Model.first(:conditions => {:attribute => value}) || raise ActiveRecord::RecordNotFound 如果它找不到匹配的记录,它不会返回 nil,而是会在找不到匹配项时引发异常。

# Raise ActiveRecord::RecordNotFound exception if 'Moby' hasn't signed up yet!
User.find_by_name!('Moby')

5.5 关联尊重私有/保护作用域

Active Record 关联代理现在尊重代理对象上方法的作用域。以前(假设 User has_one :account)@user.account.private_method 会在关联的 Account 对象上调用私有方法。这在 Rails 2.2 中失败了;如果您需要此功能,您应该使用 @user.account.send(:private_method)(或者将该方法改为 public 而不是 private 或 protected)。请注意,如果您正在覆盖 method_missing,您也应该覆盖 respond_to 以匹配该行为,以便关联可以正常工作。

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)

6.2 成员或集合路由的 Method 数组

现在您可以为新的成员或集合路由提供一个方法数组。这消除了当您需要处理多个方法时,必须定义一个接受任何动词的路由的烦恼。在 Rails 2.2 中,这是一种合法的路由声明

map.resources :photos, :collection => { :search => [:get, :post] }

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

6.4 其他 Action Controller 更改

  • 现在您可以轻松地 显示一个自定义错误页面 来处理在路由请求时抛出的异常。
  • HTTP Accept 标头现在默认情况下被禁用。您应该优先使用格式化的 URL(例如 /customers/1.xml)来指示您想要的格式。如果您需要 Accept 标头,可以使用 config.action_controller.use_accept_header = true 将其重新打开。
  • 基准测试数字现在以毫秒而不是秒的微小分数报告。
  • Rails 现在支持 HTTP-only cookie(并将其用于会话),这有助于减轻一些较新浏览器中的跨站点脚本风险。
  • redirect_to 现在完全支持 URI 方案(因此,例如,您可以重定向到 svn`ssh: URI)。
  • render 现在支持 :js 选项,以使用正确的 MIME 类型呈现纯 JavaScript。
  • 请求伪造保护已收紧,仅适用于 HTML 格式的内容请求。
  • 如果传递的参数为 nil,多态 URL 的行为会更合理。例如,调用 polymorphic_path([@project, @date, @area]),如果日期为 nil,将返回 project_area_path

7 Action View

  • javascript_include_tagstylesheet_link_tag 支持一个新的 :recursive 选项,与 :all 一起使用,这样您就可以用一行代码加载整个文件树。
  • 包含的 Prototype JavaScript 库已升级到 1.6.0.3 版本。
  • RJS#page.reload 通过 JavaScript 重新加载浏览器的当前位置。
  • atom_feed 助手现在采用 :instruct 选项,允许您插入 XML 处理指令。

8 Action Mailer

Action Mailer 现在支持邮件程序布局。您可以通过提供一个适当命名的布局来使您的 HTML 邮件与浏览器中的视图一样漂亮 - 例如,CustomerMailer 类期望使用 layouts/customer_mailer.html.erb

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

记忆化的其他功能包括 unmemoizeunmemoize_allmemoize_all,用于打开或关闭记忆化。

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_emailvendor#account_password。您还可以指定一个自定义前缀

class Vendor < ActiveRecord::Base
  has_one :account
  delegate :email, :password, :to => :account, :prefix => :owner
end

这将产生委托的方法 vendor#owner_emailvendor#owner_password

主要贡献者:Daniel Schierbeck

9.4 其他 Active Support 更改

  • ActiveSupport::Multibyte 的大量更新,包括 Ruby 1.9 兼容性修复。
  • 添加了 ActiveSupport::Rescuable,允许任何类混合 rescue_from 语法。
  • past?today?future? 用于 DateTime 类,以方便日期/时间比较。
  • Array#secondArray#fifth 作为 Array#[1]Array#[4] 的别名。
  • Enumerable#many? 用于封装 collection.size > 1
  • Inflector#parameterize 生成其输入的 URL 就绪版本,用于 to_param 中。
  • Time#advance 识别小数天数和星期数,因此您可以执行 1.7.weeks.ago1.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 是 Rails 在执行 gem 依赖项代码之前加载的 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 &lt;plugin&gt; -r &lt;revision&gt; 现在支持基于 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 的核心 DateTime 类算术。

  • Request#relative_url_root 已弃用。请改用 ActionController::Base.relative_url_root

12 致谢

发行说明由 Mike Gunderloy 编写。



返回顶部