This is due to how Mongoid optimizes field updates. In particular, since you are updating the item inside the hash field, the observer field does not pick up the update inside, because the field’s own value (indicating the hash) remains unchanged.
The solution I made was to provide a universal serializer for any complex object that I wanted to keep (e.g. Hash). This is due to the fact that this is a universal solution and just works. The downside is that it does not allow you to request internal hash fields using Mongo's built-in operations, as well as some additional processing time.
Without further solution, here is the solution. First, add this definition for the new Mongoid custom type.
class CompressedObject include Mongoid::Fields::Serializable def deserialize(serialized_object) return unless serialized_object decompressed_string = Zlib::Inflate.inflate(serialized_object.to_s) Marshal.load(decompressed_string) end def serialize(object) return unless object obj_string = Marshal.dump(object) compressed_string = Zlib::Deflate.deflate(obj_string, Zlib::BEST_SPEED) BSON::Binary.new(compressed_string) end end
Secondly, in Model (including Mongoid::Document ) use the new type:
field :my_hash_field, :type => CompressedObject
Now you can do whatever you want with the field and every time it is correctly serialized.
source share