2011-04-12 53 views
2

我玩弄了Rails 3 Rails.cache功能,當我寫一個ActiveRecord進入高速緩存,我不能讀回,更改屬性,然後寫入數據庫。我得到一個「TypeError:無法修改冷凍哈希」。我曾經使用過另一個memcache插件,但我試圖切換到Heroku,並且令人難以置信的是,我無法保存我投入Memcache的ActiveRecord條目。這將導致大量不必要的DB讀取來改變小部分信息。的Rails 3.0.3 Rails.cache.read無法寫入DB

例如,我可能會在數據庫中執行此操作。假定用戶模型:

用戶 - >登錄:串並鍵入以下內容軌Ç

user = User.new 
user.login = 'test' 
user.save 
Rails.cache.write('user:login:test', user) 
user2 = Rails.cache.read('user:login:test') 
user2.login = 'test2' 
TypeError: can't modify frozen hash 
/app/.bundle/gems/ruby/1.8/gems/activerecord-3.0.3/lib/active_record/attribute_methods/write.rb:26:in `[]=' 
    /app/.bundle/gems/ruby/1.8/gems/activerecord-3.0.3/lib/active_record/attribute_methods/write.rb:26:in `write_attribute' 
    /app/.bundle/gems/ruby/1.8/gems/activerecord-3.0.3/lib/active_record/attribute_methods/dirty.rb:61:in `write_attribute' 
    /app/.bundle/gems/ruby/1.8/gems/activerecord-3.0.3/lib/active_record/attribute_methods/write.rb:13:in `login=' 

有誰知道如何解決這個問題?

+0

您是否嘗試過3.0.6以查看您是否仍然遇到此問題? – 2011-04-12 04:15:54

回答

1

從該行獲得user2的對象值後:

user2 = Rails.cache.read('user:login:test') 

做到以下幾點:

dup_user = user2.dup # this will make a clone of the user2 object 
dup_user.login = test_2 

然後 「凍結哈希」 異常不應該再出現。

0

當你存儲在緩存中的對象,該對象被凍結。這是你永遠不應該存儲複雜對象的原因之一,比如ActiveRecord模型。

當您從緩存中讀取,對象被加載,但它仍然凍結。 ActiveRecord嘗試恢復對象狀態,但它需要更新一些內部屬性。由於對象被凍結,更新將失敗。

而不是存儲整個對象,簡單地存儲其ID和檢索即時用戶。

user = User.new 
user.login = 'test' 
user.save 
Rails.cache.write('user:login:test', user.id) 
user2 = User.find(Rails.cache.read('user:login:test')) 
user2.login = 'test2' 

這在緩存方面效率稍低一點,但是這是一條路。事實上,您不認爲在此期間用戶的其他屬性可能已被更改,並且您的對象不再代表當前狀態。

而且,這樣你的緩存存儲不會充當一個數據庫,你就可以存儲更多的緩存條目。 ID佔用的內存少於整個ActiveRecord實例。

當然,你可以使用#dup解決辦法,但它只是一個伎倆。這不是解決方案。正如我上面所解釋的,您仍然會遇到緩存完整性問題。

user = User.new 
user.login = 'test' 
user.save 
Rails.cache.write('user:login:test', user) 
user2 = Rails.cache.read('user:login:test').dup 
user2.login = 'test2'