Update hash type attribute in Mongoid

I want to update a hash type attribute in Mongoid.

Here is an example

class A include Mongoid::Document field :hash_field, :type => Hash end 

Now suppose the data is already populated, for example,

 A.last.hash_field => {:a => [1]} 

Now I wanted to update the hash and want the final result to be {:a => [1,2]}

I tried both

 a = A.last a.hash_field[:a] << 2 a.save => true a.hash_field => {:a => [1,2]} 

But when I request

 A.last.hash_field => {:a => [1]} 

Thank you, I haven’t actually updated anything. Now How can I update as I wish?

Thank Advance

+4
source share
3 answers

This may be due to the way Mongolian small copies of hashes. If so, then this may help http://spin.atomicobject.com/2011/04/13/mongoid-hash-field-types-watch-out/

Note. I have not tested the solution for your specific situation.

+3
source

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.

+2
source

My problem was a little different, but you could take advantage of how I solved it. In my mongo document, I had an array of hash card fields, and this is the form that eventually handled this:

 <% @import_file_import_configuration.fieldz.each do |fld| %> <tr> <td> <input type="number" name="import_file_import_configuration[fieldz][][index]" value='<%=fld["index"]%>'/> </td><td> <input type="textbox" name="import_file_import_configuration[fieldz][][name]" value='<%=fld["name"]%>'/> </td> </tr> <% end %> 

I store cards with two keys each ("index" and "name") in my array. This definition of my document is as follows:

 class Import::FileImportConfiguration field :file_name, type: String field :model, type: String field :fieldz, type: Array, default: [] end 
+1
source

All Articles