Ruby on rails 3 更新Mongoid中的哈希类型属性

Ruby on rails 3 更新Mongoid中的哈希类型属性,ruby-on-rails-3,mongoid,Ruby On Rails 3,Mongoid,我想更新Mongoid中的哈希类型属性 这里有一个例子 class A include Mongoid::Document field :hash_field, :type => Hash end 现在让我们假设已经有了填充数据,比如 A.last.hash_field => {:a => [1]} 现在我想更新散列,并希望最终输出为{:a=>[1,2]} 我试着 a = A.last a.hash_field[:a] << 2 a.save =>

我想更新Mongoid中的哈希类型属性

这里有一个例子

class A
 include Mongoid::Document

 field :hash_field, :type => Hash
end
现在让我们假设已经有了填充数据,比如

A.last.hash_field 
=> {:a => [1]}
现在我想更新散列,并希望最终输出为
{:a=>[1,2]}

我试着

a = A.last
a.hash_field[:a] << 2
a.save
=> true

a.hash_field
=> {:a => [1,2]}
谢谢,意思是实际上它没有更新任何东西 现在我怎样才能根据需要进行更新


提前谢谢

这可能与Mongoid浅拷贝散列的方式有关。如果是这样,那么这可能会有所帮助


注意:我没有针对您的特定情况测试解决方案

这与Mongoid如何优化字段更新有关。具体地说,由于您正在更新散列字段中的元素,字段“watcher”不会在中拾取更新,因为字段自身的值(指向散列)保持不变

我采用的解决方案是为我想要存储的任何复杂对象(例如哈希)提供一个通用序列化程序。这样做的好处是,它是一个通用的解决方案,可以正常工作。缺点是,它会阻止您使用内置的Mongo操作查询哈希的内部字段,并且还会占用一些额外的处理时间

没有进一步的告别,这里是解决方案。 首先,为新的Mongoid自定义类型添加此定义

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
其次,在您的
模型中(包括
Mongoid::Document
),使用如下新类型:

  field :my_hash_field, :type => CompressedObject

现在,您可以对该字段执行任何操作,每次都将正确序列化。

我的问题有点不同,但您可能会从我解决该问题的方式中受益。 我在mongo文档中有一个哈希映射字段数组,这是最终处理它的表单:

<% @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 %>

添加deep_拷贝和显式调用帮助了我。谢谢
<% @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 %>
class Import::FileImportConfiguration
  field :file_name, type: String
  field :model, type: String
  field :fieldz, type: Array, default: []
end