Символы, используемые в качестве хэш-ключей, преобразуются в строки при сериализации - PullRequest
7 голосов
/ 20 марта 2011

Когда я назначаю массив или хэш атрибуту документа 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]}

Это также происходит для вложенных хэшей (например, внутри массивов илидругие хеши).Есть ли способ сохранить символы в таких случаях?

Решение

Я использую YAML для ручной сериализации some_attr - YAML.dump (или Object#to_yaml) перед сохранением и YAML :: load после чтения атрибута.YAML лучше сохраняет сериализованный объект.ActiveRecord использует YAML для реализации метода класса serialize на ActiveRecord::Base.

Ответы [ 4 ]

4 голосов
/ 20 марта 2011

Скорее всего, это связано с ORM, который вы используете для предоставления слоя устойчивости для модели.Вы, вероятно, можете обернуть some_attr методом, который возвращает его в виде HashWithIndifferentAccess, к которому вы затем можете получить доступ либо с помощью строк, либо массивов.Поскольку вы используете Rails, эту функцию можно активировать, вызвав метод with_indifferent_access объекта Hash.(Если у вас есть массив объектов Hash, вам, конечно, нужно будет вызывать его для каждого из них.) Метод вернет тот же хеш, но тогда поиск символов будет работать.

Из вашего кода:

new_hash = MyMongoModel.last.some_attr.with_indifferent_access
new_hash[:a] # Will return the same as new_hash['a'] 

Надеюсь, это поможет!

3 голосов
/ 20 марта 2011

виновником здесь является сериализация BSON.когда вы сериализуете символ, используемый в качестве ключа для хэшей, он фактически переводится в строку, а когда вы спрашиваете его, вы получаете строку вместо символа.

У меня та же проблема, что и у вас, ия думаю о расширении класса Hash, чтобы включить метод для преобразования всех «строковых» ключей в символы:

к сожалению, я не на Rails, поэтому я не могу использовать with_indifferent_access, как предложено ctcherry.

0 голосов
/ 28 августа 2014

Нашел это, хорошо работает, и вы определили поле как Hash:

https://github.com/mindscratch/mongoid-indifferent-access

0 голосов
/ 20 марта 2011

Я не уверен насчет сохранения символов, но вы можете преобразовать строки обратно в символы.

str.to_sym
...