当我将一个数组或哈希分配给Mongo文档的属性时,它会正常运行 序列化除了符号,当它们用作哈希键时。简单的例子:
irb>MyMongoModel.create :some_attr => {:a => [:b,:c]}
=> #<MyMongoModel _id: 4d861c34c865a1f06a000001, some_attr: {:a=>[:b, :c]}>
irb>MyMongoModel.last
=> #<MyMongoModel _id: 4d861c34c865a1f06a000001, some_attr: {"a"=>[:b, :c]}>
请注意,some_attr
被检索为{"a"=>[:b, :c]}
,而非{:a=>[:b, :c]}
some_attr
对于嵌套的哈希(例如,在阵列或其他哈希中)也会发生这种情况。在这种情况下,有没有办法保留符号?
解决方案
我正在使用YAML在存储之前手动序列化Object#to_yaml
- YAML.dump(或serialize
),并在读取属性后使用YAML :: load。 YAML更好地保留了序列化对象。 ActiveRecord正在使用YAML在ActiveRecord::Base
上实现其{{1}}类方法。
答案 0 :(得分:4)
这很可能与您用于为模型提供持久层的ORM有关。您可以使用以some_attr
形式返回HashWithIndifferentAccess
的方法来包装with_indifferent_access
,然后您可以使用字符串或数组进行访问。由于您使用的是Rails,因此可以通过调用Hash对象上的new_hash = MyMongoModel.last.some_attr.with_indifferent_access
new_hash[:a] # Will return the same as new_hash['a']
方法来激活此功能。 (如果你有一个Hash对象数组,你当然需要在每个对象上调用它)该方法将返回相同的哈希,但随后符号查找将起作用。
从你的代码:
{{1}}
希望这有帮助!
答案 1 :(得分:3)
这里的罪魁祸首是BSON序列化。当你序列化一个用作哈希键的符号时,它实际上被翻译成一个字符串,当你再问它时,你得到的是字符串而不是符号。
我遇到了和你一样的问题,我正在考虑扩展Hash类,以包含一个将所有“字符串”键转换为:symbols的方法。
不幸的是我不在Rails上,所以我不能按照ctcherry的建议使用with_indifferent_access
。
答案 2 :(得分:0)
我不确定是否保留符号,但您可以将字符串转换回符号。
str.to_sym
答案 3 :(得分:0)
发现这个,效果很好,你已经将字段定义为Hash: