
距离上次发布 Edge Rails 文章已经有一段时间了。我真的很想念它们,而且在此期间,Edge 中发生了许多变化,无论是大是小。在这篇文章中,我将涵盖过去一周左右 Rails 中发生的所有事情。此外,您应该会看到有关当前所有正在进行的更新更频繁、更规律的更新。
这是一个相对 次要的更改,除非您仍然在 database.yml 中将 SQLite 数据库称为 dbfile。 dbfile 选项键已消失,已被更标准的 database 键取代了很长时间。因此,如果您在更新后突然看到“未指定数据库文件”错误,这可能是原因。
Sava Chankov 提供了一个补丁,修复了 Content-length HTTP 响应头在与 Ruby 1.9 和多字节字符一起使用时计算不正确的问题。现在,内容长度是根据 String#bytesize 而不是仅根据 String#size 计算的。这利用了 Ruby 1.9 内置的多字节字符支持,只要您记住始终使用正确的编码标头(例如 # encoding: utf-8)正确标记多字节文件。
一些春季清理,主要得益于 Rack 支持,让 Edge 移交了更多职责给堆栈。其中最有趣的是现在将部分内容长度计算移交给 Web 服务器,而不是直接在 Rails 中进行处理。这最大的好处不是对应用程序开发人员,而是对中间件开发人员。这意味着您不再需要在操作 HTTP 响应正文时重新计算内容长度。
这似乎不会影响 Sava 之前提到的更新,因为他的修复似乎主要影响直接通过 Rails 流式传输文件响应。
Cache 控制现在由内部 Hash 处理,而不是独立的字符串值。旧的过时方法:headers['Cache-Control'] = 'private',新的热门方法:response.cache_control[:public] = true。其他 cache_control 选项包括::public、:max_age、:must_revalidate 和非常描述性的 :extras,主要用于您的自定义标头内容。
Geoff Buesing 提供了一个有用的修复,用于 Time,特别是与 ActiveRecord 一起使用时。现在,您可以使用任何您喜欢的本地时区保存和搜索 ActiveRecord 对象,而不管您的默认时区如何配置,并且一切都将正常工作。您不再需要担心将用户的本地时间转换为您的默认应用程序时间,反之亦然。
ActiveRecord 现在可以轻松访问 ActiveModel 的 StateMachine 实现。我不知道您怎么样,但我总觉得在我的 Rails 应用程序中引入状态机,现在构建(即使是相当复杂的)状态机变得容易多了。
有关 ActiveModel::StateMachine 的示例以及了解如何使用它的方法,请查看我在 Envy Labs 上更详细的博客文章。
Paul Gillard 提交了一个补丁,现在允许您的 ActiveRecord 属性同时具有自定义后缀(这其实不是新的)和前缀(哇,那是新的!)。这使您可以使用 attribute_method_prefix、attribute_method_suffix,以及现在 attribute_method_affix。虽然这听起来可能有点傻,但请看这个
class Person < ActiveRecord::Base
attribute_method_affix :prefix => 'me_mateys_', :suffix => '_is_in_pirate?'
private
def me_mateys_attribute_is_in_pirate?(attr)
send(attr).to_s =~ /\bYAR\b/i
end
end
person = Person.find(1)
person.name #=> 'Paul Gillard'
person.profession #=> 'A Pirate, yar!'
person.me_mateys_name_is_in_pirate? #=> false
person.me_mateys_profession_is_in_pirate? #=> true
好吧,这仍然有点傻,但希望您能明白我的意思,并能想到一些您自己的使用场景。所以,基本上,现在您可以添加自己的动态 ActiveRecord 方法,这些方法可能会影响其任何或所有属性。
Paul Gillard 发布了另一个有用的补丁,利用了之前提到的那个,现在为我们提供了这个语法糖:reset_attribute! 他甚至还提供了一个海盗来展示这个新宝藏
pirate = Pirate.create!(:catchphrase => 'Yar!')
pirate.catchphrase = 'Ahoy!'
pirate.reset_catchphrase!
assert_equal "Yar!", pirate.catchphrase
assert_equal Hash.new, pirate.changes
assert !pirate.catchphrase_changed?
没有人喜欢肮脏的海盗。