2013-11-22 53 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使用CString(e_name)鍵映射和序列化爲BSON文檔(或嵌入式文檔) 。參考:

http://bsonspec.org/#/specification

所以密鑰字符串化的系列化,倒塌字符串鍵和符號鍵一起失去的區別。 將反序列化轉換回Ruby哈希,當前驅動程序映射到字符串鍵。 在MongoDB,Inc. Ruby驅動程序(mongo gem,github mongo-ruby-driver)版本1.8, 中,我們試圖通過定義我們自己的HashWithIndifferentAccess ala Rails, 來解決此問題,但內部使用符號而不使用字符串。 但是,我們遇到了JRuby的Java擴展的複雜問題,不得不恢復該功能。參考:

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

在2.0版本中,我們計劃使用新的BSON-紅寶石https://github.com/mongodb/bson-ruby實現 這主要是紅寶石以最小的C和Java擴展。 我們應該能夠重新審視實施。

有一些性能方面的考慮。 由於生成了新的字符串,因此目前符號#to_s比預期的要貴。 看起來像一個很好的Ruby核心語言優化將是記憶字符串。因此,序列化符號鍵實際上比序列化字符串鍵更昂貴。

請隨意打開一個新的Ruby故障單並請求「查詢應該返回一個帶有無差別訪問的哈希」。 它將幫助我們優先考慮。

相關問題