Ruby 2.1.1 中 Hash#reject 的回归

在 Ruby 2.1.0 或更早版本中,任何继承 Hash 类的 reject 方法都会返回该类自身的对象。但在 Ruby 2.1.1 中,此行为意外地更改为始终返回一个普通的 Hash 对象,而不是继承的类。

class SubHash < Hash
end

p Hash.new.reject { }.class
#=> 2.1.0: Hash, 2.1.1: Hash
p SubHash.new.reject { }.class
#=> 2.1.0: SubHash, 2.1.1: Hash

(确切地说,实例变量等额外状态也不会被复制。)

Ruby 2.1.1 不应包含此类行为更改,因为随着 Ruby 2.1.0 的发布,我们已经更改了我们的版本策略,因此 Ruby 2.1.1 是一个补丁级别版本,不应破坏向后兼容性。

此回归可能会影响许多库,其中一个例子是 Rails 的 HashWithIndifferentAccessOrderedHash。它们已经被破坏:Rails 的问题 #14188

此行为将在 Ruby 2.1.2 中恢复到 2.1.0 的行为,但预计将成为 Ruby 2.2.0 的默认行为:功能 #9223。因此,我们建议您修复代码以适应此行为更改。

此意外情况是由一个缺失的向后移植提交引起的。有关更多详细信息,请参阅 http://blog.sorah.jp/2014/03/10/hash-reject-regression-in-ruby211

对于由此带来的任何不便,我们深感抱歉,并感谢您的支持。