Hi,
While writing yet another Ruby ODM for mongoDB, I ran into a
significant bug in the implementation of OrderedHash. The #each
implementation returns the results of the iteration over the key array
and not the OrderedHash itself. This manifests any time you use the
results of #each or #delete_if (which delegates to #each) -- the
common case being chaining as the AS diff method does below.
The patch (with test) is here:
http://github.com/leshill/mongo-ruby-driver/commit/8bc357934ed27b483cabfcdd138019e1fd192d24
Console session showing the behavior contrasted to a Ruby Hash and
ActiveSupport's OrderedHash
>> hash = Hash.new
=> {}
>> hash['a'] = 1
=> 1
>> hash
=> {"a"=>1}
>> as_ohash = ActiveSupport::OrderedHash.new
=> #<OrderedHash {}>
>> as_ohash['b'] = 2
=> 2
>> as_ohash
=> #<OrderedHash {"b"=>2}>
>> hash.diff(as_ohash)
=> {"a"=>1, "b"=>2}
>> as_ohash.diff(hash)
=> #<OrderedHash {"a"=>1, "b"=>2}>
>> id = db.collection('tester').save(hash)
=> #<Mongo::ObjectID:0x17b14c4 @data=[74, 198, 202, 247, 37, 87, 171,
54, 139, 0, 0, 2]>
>> m_ohash = db.collection('tester').find(hash).next_object
=> {"_id"=>#<Mongo::ObjectID:0x17aa7f0 @data=[74, 198, 202, 247, 37,
87, 171, 54, 139, 0, 0, 2]>, "a"=>1}
>> m_ohash.class
=> OrderedHash
>> hash.diff(m_ohash)
TypeError: can't convert Array into Hash
from /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.3.4/lib/
active_support/core_ext/hash/diff.rb:14:in `merge'
from /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.3.4/lib/
active_support/core_ext/hash/diff.rb:14:in `diff'
from (irb):34
>> m_ohash.diff(hash)
NoMethodError: undefined method `merge' for ["_id"]:Array
from /usr/local/lib/ruby/gems/1.8/gems/activesupport-2.3.4/lib/
active_support/core_ext/hash/diff.rb:14:in `diff'
from (irb):35
Les Hill
les...@gmail.com