2007 年 9 月 30 日星期日

Rails 2.0:预览版本

发布者:David

各位敬请期待,Rails 2.0 就要发布了。在为其添上最后官印之前,我们将会推出几个试用版阶段。第一个就是这个预览版,此版本能让您体验功能几乎完全成熟的佳肴。

我们可能会修改几处内容或添加一些其他内容,但从总体上看,Rails 2.0 的外观和感受将是这样的。经过这次发布尝试后,我们将准备发布一个或两个候选版本(或三个,视需要而定)。最后便是发布最终版。

在发布 2.0 之前,我们还会推出 1.2.4,其中将包含一系列错误修复和最新的废弃警告,以便您为将现有应用程序升级到 2.0 标准做好准备。

好了,进程就说到这里。让我来简单为您介绍 Rails 2.0 的新功能

Action Pack:资源

这是 2.0 的主要操作部分。我们对 RESTful 生活方式进行了多项改进。首先,我们舍弃了自定义方法的分号,而是采用常规斜杠。因此,现在的 /people/1;edit 变成了 /people/1/edit。我们还添加了 namespace 特性来路由资源,这样就能非常轻松地限制管理界面等内容

map.namespace(:admin) do |admin| admin.resources :products, :collection => { :inventory => :get }, :member => { :duplicate => :post }, :has_many => [ :tags, :images, :variants ] end

该代码将为您提供诸如 inventory_admin_products_url 和 admin_product_tags_url 等命名路由。为了跟踪这种命名路由爆炸式增长,我们添加了“rake routes”任务,此任务将列出 routes.rb 创建的所有命名路由。

我们还发起了一项新惯例:默认情况下,所有基于资源的控制器都将采用复数形式。这能让单一资源在多个上下文中被映射,而且仍然引用相同的控制器。示例


  # /avatars/45 => AvatarsController#show
  map.resources :avatars
  
  # /people/5/avatar => AvatarsController#show 
  map.resources :people, :has_one => :avatar

Action Pack:多视图

除了对资源的改进之外,我们还对多视图进行了改进。我们已经有了 #respond_to,但我们更进了一步,使其深入到模板中。我们已经将模板的格式从其渲染引擎中分离出来。因此,现在 show.rhtml 变成 show.html.erb,后者是默认渲染 show 操作的模板(该操作在其 respond_to 中声明了 format.html)。现在您还可以拥有诸如 show.csv.erb 之类的模板,该模板的目标是 text/csv,但它也使用默认的 ERB 渲染器。

因此,模板的新格式为 action.format.renderer。以下是一些示例

  • show.erb:针对所有格式显示相同的模板
  • index.atom.builder:使用 Builder 格式(以前称为 rxml)针对 application/atom+xml MIME 类型渲染 index 操作
  • edit.iphone.haml:使用自定义的 HAML 模板引擎(默认情况下未包含)来呈现自定义 Mime::IPHONE 格式的编辑操作

说到 iPhone,我们简化了“伪”类型的声明,这些声明仅用于内部路由。比如当您希望有一个专门的 HTML 界面只针对 iPhone 时。您只需执行以下类似的操作


  # should go in config/initializers/mime_types.rb
  Mime.register_alias "text/html", :iphone

  class ApplicationController < ActionController::Base
    before_filter :adjust_format_for_iphone
  
    private
      def adjust_format_for_iphone
        if request.env["HTTP_USER_AGENT"] && request.env["HTTP_USER_AGENT"][/(iPhone|iPod)/]
          request.format = :iphone
        end
      end
  end
  
  class PostsController < ApplicationController
    def index
      respond_to do |format|
        format.html   # renders index.html.erb
        format.iphone # renders index.iphone.erb
      end
    end
  end

您应在 config/initializers/mime_types.rb 文件中声明自己的 MIME 类型别名。此文件默认包含在所有新应用程序中。

Action Pack:记录标识

在为资源提供新功能的同时,对于处理 URL 的控制器和视图方法进行了一些简化。我们添加了一些约定,以便在运行时将模型类转为资源路由。示例


  # person is a Person object, which by convention will 
  # be mapped to person_url for lookup
  redirect_to(person)
  link_to(person.name, person)
  form_for(person)

Action Pack:HTTP 簇拥者

正如您可能了解的那样,Rails 2.0 中的 Action Pack 的工作重点是更加接近 HTTP 及其所有优点。资源、多种表示,但还有更多。我们添加了一个新模块来处理 HTTP 基本身份验证,这最终证明是通过 SSL 执行 API 身份验证的出色方法。它的使用极其简单。下面是一个示例(在 ActionController::HttpAuthentication 中还有更多示例)


  class PostsController < ApplicationController
    USER_NAME, PASSWORD = "dhh", "secret"

    before_filter :authenticate, :except => [ :index ]

    def index
      render :text => "Everyone can see me!"
    end

    def edit
      render :text => "I'm only accessible if you know the password"
    end

    private
      def authenticate
        authenticate_or_request_with_http_basic do |user_name, password| 
          user_name == USER_NAME && password == PASSWORD
        end
      end
  end

我们还让您在逻辑单元中对 JavaScript 和样式表文件进行组织变得更加容易,而无需被请求海量文件时的 HTTP 开销所累。在生产环境中,使用 javascript_include_tag(:all, :cache => true) 会将 public/javascripts/.js 转换为单个 public/javascripts/all.js 文件,但在开发环境中仍然保持文件分离,因此您可以在不清除缓存的情况下迭代工作。

同样,我们还添加了一个选项来欺骗那些不想自己对请求进行流水线的浏览器。如果您将 ActionController::Base.asset_host = “assets%d.example.com” 设置,我们会自动将您的资源调用(例如 image_tag)分配到 asset1 至 asset4。这允许浏览器一次打开更多连接,并增加您的应用程序的感知速度。

Action Pack:安全性

开箱即用地创建安全应用程序总是让人愉快,在 Rails 2.0 中,我们从多个方面实现了这一目标。最重要的是,我们现在提供了一种处理 CRSF 攻击的内置机制。通过在所有表单和 Ajax 请求中包含一个特殊令牌,您可以防止来自应用程序外部的请求。所有这些功能在新 Rails 2.0 应用程序中默认开启,您还可以使用 ActionController::Base.protect_from_forgery(请参阅 ActionController::RequestForgeryProtection 了解更多内容)在现有应用程序中非常轻松地开启该功能。

我们还让处理XSS代码注入攻击变得更加容易,同时仍然允许用户在你的页面中嵌入HTML。旧的 TextHelper#sanitize 方法从黑名单方法(很难保持安全)变成了白名单方法。如果你已经在使用sanitize,那么你将自动获得更好的防护。你还可以使用 sanitize 微调允许的默认标签。详情请参阅 TextHelper#sanitize。

最后,我们增加了对HTTP只读 cookie的支持。它们尚未得到所有浏览器的支持,但你可以在支持的浏览器中使用它们。

Action Pack:异常处理

与针对每个操作,在共享级别拯救许多常见异常会更好。这始终有可能通过覆盖rescue_action_in_public实现,但然后你必须自己推出用例语句并调用 super。切。因此,我们现在有一个名为 rescue_from 的类级别宏,你可以使用它来声明性地将特定异常指向给定操作。示例


  class PostsController < ApplicationController
    rescue_from User::NotAuthorized, :with => :deny_access
    
    protected
      def deny_access
        ...
      end
  end

Action Pack:其他

另一个值得注意的是 AtomFeedHelper,它使用更高级的 Builder 语法创建 Atom Feed 时显得更加简单。简单示例


  # index.atom.builder:
  atom_feed do |feed|
    feed.title("My great blog!")
    feed.updated((@posts.first.created_at))
  
    for post in @posts
      feed.entry(post) do |entry|
        entry.title(post.title)
        entry.content(post.body, :type => 'html')
  
        entry.author do |author|
          author.name("DHH")
        end
      end
    end
  end

我们进行了一些性能改进,因此资产标记调用现在便宜得多,并且我们正在缓存简单命名的路由,并且也让它们快得多。

最后,我们在官方 Rails SVN上将 in_place_editor 和 autocomplete_for 踢出了插件。

活动记录:性能

活动记录已经进行了大量的修复和小的调整,但其主要的新功能有点少。我们添加的新功能是简单的 Query Cache,它将识别来自同一请求内的类似SQL调用,并返回缓存结果。对于使用 :include 或其他机制可能难以处理的 N+1 情况,这尤其好。我们还大幅提高了fixture的性能,这使得大多数基于正常使用fixture的测试套件将快50-100%。

活动记录:性感的迁移

有一种新的备用格式,可以在更有效率的格式中声明迁移。之前你会这么写

create_table :people do |t| t.column, “account_id”, :integer t.column, “first_name”, :string, :null => false t.column, “last_name”, :string, :null => false t.column, “description”, :text t.column, “created_at”, :datetime t.column, “updated_at”, :datetime end

现在你可以这么写

create_table :people do |t| t.integer :account_id t.string :first_name, :last_name, :null => false t.text :description t.timestamps end

活动记录:XML输入,JSON输出

活动记录已经支持了一段时间的XML序列化。在 2.0 中,我们还添加了反序列化,因此你可以说 Person.new.from_xml(“David”) 并获得您的预期。我们还向 JSON 中添加了序列化,它支持和 XML 序列化相同的语法(包括嵌套关联)。只需执行 person.to_json 便可开始运行。

ActiveRecord:丢弃一些重量

为了让 ActiveRecord 更精简,我们移除了 acts_as_XYZ 功能,并将它们放置在 Rails SVN 代码库上单个插件中。所以如果您正在使用 acts_as_list,您只需执行 ./script/plugin install acts_as_list,一切将像从未发生过一样继续进行。

更彻底的是,我们还将所有商业数据库适配器移入到它们自己的 gem 中。所以 Rails 现在只提供用于 MySQL、SQLite 和 PostgreSQL 的适配器。这些是我们易于测试并且愿意测试的数据库。但这并不意味着商业数据库被抛在一边。相反,它们现在可以与 Rails 主发行版独立发布。这可能是一件好事,因为商业数据库常常需要大量例外的不断修补,才能运行良好。

商业数据库适配器现在存在于 Gem 中,所有这些 gem 都遵守同一命名约定:activerecord-XYZ-adapter。所以如果您 gem install activerecord-oracle-adapter,您将立即在该计算机上的所有 Rails 应用程序中将 Oracle 作为适配器选项。您不必在应用程序中更改一行来使用它。

这也意味着,新的数据库适配器更容易在 Rails 世界中获得关注。只要您根据发布的约定打包您的适配器,用户只需安装该 gem 就可以开始运行。

ActiveRecord:with_scope 具有少许语法

为了阻止人们在控制器(尤其是过滤器)中误用 ActiveRecord::Base.with_scope ,它已经受到保护。相反,现在建议您只在模型自身中使用它。这是它的设计目的,在逻辑上仍然很贴合。但是,这当然都与鼓励和阻止有关。如果您权衡了利弊,仍然希望在模型外使用 with_scope,您可以始终通过 .send(:with_scope) 调用它。

ActionWebService 出局,ActiveResource 入局

SOAPREST 争论中,Rails 已选边站,这可能不会让人惊讶。除非您绝对必须出于集成目的使用 SOAP,我们强烈建议您不要这么做。作为该建议的自然延伸,我们已将 ActionWebService 从默认包中拉出。它只是一个 gem 安装 actionwebservice,但它传递了一个重要的信息。

与此同时,我们已经将新的 ActiveResource 框架从测试版放入了默认版本中。ActiveResource 就像 ActiveRecord,但用于资源。它遵循类似的 API,并配置为使用基于资源的方法工作的 Rails 应用程序。例如,ActiveResource 可以访问一个原生态的脚手架。

ActiveSupport

ActiveSupport 中没有什么新东西。我们有一堆新方法,例如 Array#rand,用于从数组中获取随机元素,Hash#except,用于根据不需要的键筛选哈希,以及为日期添加的许多扩展。我们还使用 assert_difference 使测试更加简洁。除此之外,基本上只有修复和调整。

Action Mailer

这是一次非常适度的 Action Mailer 更新。除了修复一些错误外,我们还添加了为测试套件注册替代模板引擎和 assert_emails 的选项,其工作方式如下:

  1. 断言在一个块内发送的电子邮件数量
    assert_emails 1 do
    post :signup, :name => ‘Jonathan’
    end

Rails:调试器回来了

为了将所有东西联系在一起,我们对 Rails 进行了大量的改进。其中我最喜欢的是以调试器的形式返回断点。它是一个真正的调试器,而不仅仅是一个 IRB 转储。您可以前后浏览、列出当前位置等等。一切都来自 ruby-debug 宝石的优雅注释。因此,您必须安装它才能让新调试器工作。

要使用调试器,您只需安装此宝石,将 “debugger” 放在应用程序中的某处,然后使用 —debugger 或 -u 启动服务器。当代码执行调试器命令时,您将立即在运行服务器的终端中获得它。无需 script/breakpointer 或其他任何东西。您也可以在测试中使用调试器。

Rails:清理您的环境

在使用 Rails 2.0 之前,config/environment.rb 文件中的每处都会被所有种类的临时配置详细信息阻塞。现在,您可以在自包含文件中收集这些元素,并将其放在 config/initializers 中,它们将自动加载。新的 Rails 2.0 应用程序包含两个示例,即 inflections.rb(用于您自己的复数形式规则)和 mime_types.rb(用于您的自己的 MIME 类型)。这应确保您只需在 config/environment.rb 中保留默认值即可。

Rails:更简单的插件排序

现在,我们已经从 Rails 中提取了大量的素材并放入插件中,您很可能拥有其他依赖此功能的插件。这可能需要您在您自己的 acts_as_extra_cool_list 插件之前加载 acts_as_list,以便后者扩展前者。

以前,这要求您在 config.plugins 中指定所有插件。当您只想说 “我只关心在其他所有内容之前加载 acts_as_list” 时,这是一个大麻烦。现在,您可以使用 config.plugins = [ :acts_as_list, :all ] 来执行此操作。

以及数百个其他改进

我上面提到的只是 2.0 全套软件包中很小的一部分。我们已经把数百个错误修复、微调和功能增强融入到 Rails 2.0 中。所有这些都离不开众多热心贡献者不知疲倦地工作,以在细微但重要的方面改善该框架。

我鼓励大家仔细查看 CHANGELOG,了解所有更改内容。

那么我该如何升级?

如果你想把你的应用程序迁移至 Rails 2.0,首先应该把它迁移至 Rails 1.2.3。这将包括大多数我们从 2.0 中剔除的内容的弃用警告。因此,如果你的应用程序能在 1.2.3 中良好运行而没有弃用警告,那么它很有可能可以在 2.0 中直接运行。当然,如果你使用分页(例如),你需要安装 classic_pagination 插件。如果你使用 Oracle,则需要安装 activerecord-oracle-adapter gem。所有提取的内容以此类推。

要通过 gem 安装预览版本,请执行以下操作

gem install rails —source http://gems.rubyonrails.org

要从此 SVN 标记尝试,请使用

rake rails:freeze:edge TAG=rel_2-0-0_PR

我们还将很快推出 Rails 1.2.4,其中将包括更多弃用内容,以便在 2.0 发布之前向你发出警告。

在任何情况下,如同我在一开始所解释的,这是一个预览版本。利用它来感受一下 2.0。查看你的当前应用程序可能需要哪些调整的地方。并尝试从头创建新的应用程序以了解新默认设置。几周后我们将继续进行候选版本。

感谢所有参与开发 Rails 2.0 的人。我们已经为此努力了六个多月,现在终于能够与更广泛的受众分享它真是太棒了。尽情享受吧!