2007 年 1 月 19 日星期五

Rails 1.2:REST 推崇的 HTTP 崇拜锦标赛兼 UTF-8 狂欢

David 撰写

赶紧拿出你的派对气球和滑稽帽子吧,我们已经准备好了。是的,阁下,Rails 1.2 终于光荣发布了。最初,我们预计花费更短的时间来把一切都列队排列好(即便如此,在此公布之前我们在 1.2.0 到 1.2.1 之间遇到了一个小缺陷,导致我们直接跳过了该缺陷)。

所以,希望这会值得期待。开什么玩笑?当然值得等待。我们利用 RESTful 韵味,为面向资源的体系结构提供了新的鼓励。我们逐渐关注 MIME 类型、HTTP 状态代码以及同一资源的多重表示形式。当然,还有多字节安全 UTF-8 纠缠的国际风情。

这些只是部分头条功能。除此之外,还有数量惊人的抛光功能。仅 Action Pack 的 CHANGELOG 就包含大约两百个条目。其上,Active Record 又具有大约一百七十个条目。

所有这些都得益于我们伟大而光荣的社区所做的惊人工作。来自世界各地的人们做出了自己的微薄贡献,无论大小,来提升你的笑容。伙计们,这就是爱。

一如既往,你可以通过 gem 获得最新、最棒的版本

gem install rails —include-dependencies

…或者,如果你更倾向于直接冻结它,则可以

rake rails:freeze:edge TAG=rel_1-2-1

如果你使用 gem,请记住在 config/environment.rb 中更改你的版本绑定。否则,你仍会受制于先前使用的任何旧版本。

但请注意,这是一次大规模升级。Rails 的一些主要组件被弃用并彻底重写(包括路由和自动加载)。我们尽了最大努力保持向后兼容性。我们已经举行了多次发布候选人例会,以帮助每个人实现这一目标。

但这可能并不完美,见鬼,什么是完美的呢?因此,最好在考虑部署之前给你的应用程序进行一次充分、彻底的测试。但当然,你已经成为一个优秀的测试人员,你需要做的就是进行一次“rake”来查看是否一切都通过了,对吧?

如何学习 Rails 1.2 的全部内容

作为开场白,我将重点介绍有关新功能的 RC1 发行说明的重播。但这仅重播了要点。真正的粉丝会想仔细阅读 来自 API 的 CHANGELOG

对于其他人来说,当然也有一个更简单的方法,即直接购买第二版的 使用 Rails 进行敏捷 Web 开发。此版本编写得非常适合 1.2,并且比你从 CHANGELOG 中找到的内容包含更多详细的指导。

因此,第二版在仅仅三周内就售出了 15,000 本第一版,这不足为奇。不过,请放心,第二版应该已经在商店中销售。为了获得即时的满足,没有什么比从 Pragmatic 图书网站上购买 PDF+Book 组合更好的了。

REST 和资源

REST 和一般的 HTTP 赞赏是 Rails 1.2 的明星。最初,在 RailsConf 主题演讲 中向公众介绍了这些功能的大部分内容。观看一下该演讲,了解为什么 REST 对 Rails 很重要。

然后开始考虑你的应用程序如何变得更加 RESTful。你也可以将 15 动作控制器转变为 2-3 个新控制器,每个控制器包含一个 CRUDing love 的单一资源。这是隐藏最大好处的地方:实现者可以减少控制器的设计复杂性并最终得到一个在通用网络中表现更好的应用程序的明确方法。

为了帮助实现此过渡,我们提供了一个脚手架生成器,它可以创建一个存根 CRUD 接口,就像原始脚手架一样,不过采用的是 RESTful 方式。你可以使用 “script/generate scaffold_resource” 来试用它。如果不提供任何参数,你将获得有关其工作原理和创建的内容的简要介绍。

将所有这些内容捆绑在一起的唯一真正的 API 元素是新的 map.resources,它用于替代 map.connect,以便为 HTTP 动词爱构建一个基于资源的控制器。然后,一旦你有了资源控制器,就可以使用我们的动词仿真链接 link_to "Destroy", post_url(post), :method => :delete 进行链接。同样,运行资源脚手架将使你了解其所有工作的原理。

格式和 respond_to

虽然 respond_to 自 Rails 1.1 起就一直存在,但在 1.2 中我们添加了小小的调整,这最终对该功能的立即有用性产生很大影响。那就是 :format 的魔力。所有新应用程序都将有一个其他默认路由:map.connect ':controller/:action/:id.:format'。安装此路由后,想象以下示例

class WeblogController < ActionController::Base def index @posts = Post.find :all respond_to do |format| format.html format.xml { render :xml => @posts.to_xml } format.rss { render :action => “feed.rxml” } end end end

获取 /weblog # 返回浏览器接受头 HTML获取 /weblog.xml # 返回 XML 获取 /weblog.rss # 返回 RSS

不再需要使用 Accept 头来完成这一点。这使得一切变得更加容易。只需向 URL 添加 .xml,即可在浏览器中浏览您的 API。用不着特意查找新闻阅读器的线索,只需使用 .rss 即可。所有这些操作都自动适用于页面和操作缓存。

当然,这种格式的优点最好与 map.resources 结合使用,它自动确保了所有内容都能完美运作。资源生成器甚至包含一个关于格式使用 .xml 的示例,所以 /posts/5.xml 将自动关联在一起。非常棒!

多字节

Unicode 来了!Rails 一直都能存储和显示 unicode,没有问题,但若要截断、反转或获取 UTF-8 字符串的确切长度,操作会更复杂一些。您需要自己琢磨 KCODE,虽然很多人使用起来也不错,但它并不像您想象的(甚至期待的)那样即插即用(或可能甚至预期的那样)。

所以,由于 Ruby 直到明年此时才能支持多字节,Rails 1.2 引入了 ActiveSupport::Multibyte 用于处理 Unicode 字符串。调用字符串上的 chars 方法,开始使用字符(而不是字节)。

设想字符串为“€2.99”。如果我们在字节级别对其进行操作,很容易造成结果惨不忍睹

‘€2.99’[0,1] # => “\342” ‘€2.99’[0,2] # => “?” ‘€2.99’[0,3] # => “€”

€ 字符占三个字节。因此,您不仅不能轻松地在字节级别对其进行操作,String#first 和 TextHelper#truncate 也无法正常使用。过去,该情况会出现以下问题

‘€2.99’.first # => ‘\342’ truncate(‘€2.99’, 2) # => ‘?’

当然,在 Rails 1.2 中,问题迎刃而解

‘€2.99’.first # => ‘€’ truncate(‘€2.99’, 2) # => ‘€2’

TextHelper#truncate/excerpt 和 String#at/from/to/first/last 自动执行 .chars 转换,但如果您需要自己操作或显示长度,请务必调用 .chars。例如

您已编写 <%= @post.body.chars.length %> 个字符。

在 Rails 1.2 中,我们假设您希望一开始就使用 unicode。因此,操作渲染的默认字符集也是 UTF-8(您可以使用 ActionController::Base.default_charset=(encoding) 设置另一种字符集)。KCODE 也自动设置为 UTF-8。

观看屏幕快照。(但请注意,不再需要手动设置 KCODE

对 Unicode 的需求最大,但 Multibyte 已做好准备处理其他编码(例如 Shift-JIS),就像它们已实现的那样。请为您的编码扩展 Multibyte。

感谢 Manfred Stienstra、Julian Tarkhanov、Thijs van der Vossen、Jan Behrens 和(其他人?)创建此库。

路由

Action Pack 对 Routes 进行了全新的实现,速度更快、更安全,但它也更加严格。分号和句点是分隔符,因此不再匹配原来匹配“/download/history.txt”的“/download/:file”路由。使用“:requirements => {:file => /.*/ }”可匹配该句点。

自动加载

我们修复了一个允许 Ruby 标准库中的库在引用时自动加载的漏洞。以前,如果您仅仅引用 Pathname 常量,我们将自动加载 pathname.rb。现在不行了,您需要手动添加“需要‘pathname’”了。

我们还改进了模块加载功能,这意味着对 Accounting::Subscription 的引用将查找 app/models/accounting/subscription.rb。同时,这意味着仅仅引用 Subscription 不会 在 app/models 的任何子目录中查找 subscription.rb。将只尝试加载 app/models/subscription.rb。如果您出于某些原因依赖这一功能,仍可以在 config/environment.rb 中将 app/models/accounting 添加到 config.load_paths 以重新获得此功能。

Prototype

为了更好地符合 HTML 规范,Prototype 的基于 Ajax 的表单不再对禁用的表单元素进行序列化。如果您依赖禁用的字段提交,请更新您的代码。

为了保持一致,Prototype 的 Element 和 Field 方法不再采用任意数量的参数。这意味着,如果您在手工编写的 JavaScript 中使用了 Element.toggle、Element.show、Element.hide、Field.clear 和 Field.present,则需要更新您的代码(Prototype 助手已更新,可自动生成正确的内容)。


// if you have code that looks like this
Element.show('page', 'sidebar', 'content');
// you need to replace it with code like this
['page', 'sidebar', 'content'].each(Element.show);

Action Mailer

所有电子邮件默认使用 MIME 1.0 版,因此您必须更新您的邮件程序单元测试:@expected.mime_version = '1.0'

弃用

自 Rails 1.0 以来,我们一直保持一个稳定的、向后兼容的 API,因此您的应用可以在不使用大量工作的情况下迁移到新版本。该 API 中的一些功能现在感觉象是我们的 大一新生 15,所以我们开始减肥了。Rails 1.2 弃用了几个功能,它们现在有更出色的替代功能,或者更适合用作插件。

弃用不是威胁,它是一种承诺!这些功能将在 Rails 2.0 中彻底消失。您可以在 1.2 中继续使用它们,但您会受到批评:在您的测试结果和日志文件中寻找难看的弃用警告。

为您的 1.0 时代代码采用一些现代风格。若要开始,运行您的测试并关注警告。