2013-11-22 1 views
1

Я использую Mongoid в моем проекте, и есть модель, которая имеет поле хэш:Почему ключи поля хэш-кода модели не сохраняются в виде символов?

field :settings, type: Hash 

Я определил after_create обратного вызова, чтобы установить некоторые настройки после создания модели:

after_create :set_settings 
def set_settings 
settings[:test] = true 
save! 
end 

но теперь я видеть, что хэш сохраняется со строковыми ключами и не с помощью клавиш символов:

{"test"=>true} 

, а затем я попытался symbolize_keys, как это :

settings[:test] = true 
settings.symbolize_keys! 
save! 

но это не сработало.

Дело в том, что если мы будем вручную выполнять эти процедуры на консоли, хеш сохраняется с символьными клавишами!

любая идея?

ответ

1

Rails использует класс HashWithIndifferentAccess, чтобы разрешить доступ к ключам хеша с помощью строк или символов, не связанных с базовой реализацией. Я подозреваю, что где-то за кулисами ваш хэш превращается в один из этих объектов.

Что касается того, почему ключи сохранены в виде строк, я подозреваю, что это связано с тем фактом, что symbols are not garbage collected, и этот факт может быть использован для разрешения атак DOS, если вы не будете осторожны.

1

В MongoDB Ruby Hash отображает и сериализует документ BSON (или встроенный документ) с (e_name) ключами, которые являются CStrings. Справка:

http://bsonspec.org/#/specification

Так ключи строковая сериализации, разрушаясь строковыми ключами и ключи символов вместе и потерей различия. При десериализации обратно в хеши Ruby текущие драйверы сопоставляются строковыми ключами. В драйвере MongoDB, Inc. Ruby (mongo gem, github mongo-ruby-driver) версии 1.8, мы попытались решить эту проблему, указав наш собственный HashWithIndifferentAccess ala Rails, , но с символами внутри, а не с строками. Однако мы столкнулись с осложнениями с расширением Java для JRuby и должны были отменить эту функцию. Справка:

https://jira.mongodb.org/browse/RUBY-434

В версии 2.0 мы планируем использовать новую реализацию BSON-рубиновый https://github.com/mongodb/bson-ruby, который в основном рубин с минимальным C и расширений Java. Мы должны иметь возможность вернуться к реализации.

Есть некоторые соображения производительности. В настоящее время символ # to_s стоит дороже, чем ожидалось по мере создания новой строки. Кажется, что хорошая оптимизация языка рубинов Ruby будет напоминать строку. Таким образом, сериализация символьных клавиш на самом деле дороже, чем сериализация строковых ключей.

Пожалуйста, не стесняйтесь, чтобы открыть новый билет на Ruby и запросить «Запросы должны вернуть Hash w/Indifferent Access». Это поможет нам расставить приоритеты.

Смежные вопросы