2012-06-27 15 views
10
के साथ सक्रिय रिकॉर्ड प्रश्नों कैशिंग

मेरे संस्करण है:भ्रम Rails.cache.fetch

  • रेल: 3.2.6
  • दल्ली: 2.1.0

मेरे env है:

  • config.action_controller.perform_caching = true
  • config.cache_store =: dalli_store, 'loc alhost: 11211 ', {: नाम स्थान =>' MyNamespace '}

जब मैं लिखना:

Rails.cache.fetch(key) do 
    User.where('status = 1').limit(1000) 
end 

उपयोगकर्ता मॉडल संचित नहीं किया जा सकता है। अगर मैं

Rails.cache.fetch(key) do 
    User.all 
end 

का उपयोग कैश किया जा सकता है। क्वेरी परिणाम कैश कैसे करें?

उत्तर

30

क्योंकि कारण है

User.where('status = 1').limit(1000) 

रिटर्न एक ActiveRecord::Relation जो के रूप में वास्तव में है एक सवाल नहीं, सामना करना। रेल गुंजाइश को पकड़ता है।

यदि आप क्वेरी को कैश करना चाहते हैं, तो आपको अंत में एक क्वेरी विधि का उपयोग करने की आवश्यकता है, जैसे #all

Rails.cache.fetch(key) do 
    User.where('status = 1').limit(1000).all 
end 

कृपया ध्यान दें कि यह एक अच्छा विचार ActiveRecord वस्तुओं कैश करने के लिए कभी नहीं है। किसी ऑब्जेक्ट को कैशिंग करने से असंगत राज्य और मूल्य हो सकते हैं। लागू होने पर आपको हमेशा प्राचीन वस्तुओं को कैश करना चाहिए। इस मामले में, आईडी को कैश करने पर विचार करें।

ids = Rails.cache.fetch(key) do 
    User.where('status = 1').limit(1000).pluck(:id) 
end 
User.find(ids) 

आप इस मामले में तर्क दे सकता है कि User.find के लिए एक कॉल यह हमेशा मार डाला है। यह सच है, लेकिन प्राथमिक कुंजी का उपयोग कर क्वेरी तेज है और आप पहले बताई गई समस्या के आसपास आते हैं।इसके अलावा, सक्रिय रिकॉर्ड ऑब्जेक्ट्स कैशिंग महंगा हो सकती है और आप केवल एक सिंगल कैश एंट्री के साथ सभी मेमकैड मेमोरी भरने को समाप्त कर सकते हैं। कैशिंग आईडी इस समस्या को भी रोक देगा।

+0

thx। अगर मेरे पास एक श्रेणी मॉडल है, तो इसमें 100 से कम रिकॉर्ड हो सकते हैं, मैं श्रेणी कैश करता हूं। यह एक अच्छा विचार है? cateogry id – tinylian

+0

कैश नहीं करें या मैं पहले श्रेणी.all को जेसन में बदलता हूं, और उन्हें memcached में कैश करता हूं? – tinylian

+1

यह एक बहुत ही महत्वपूर्ण और सूक्ष्म मुद्दा है; हमने महसूस किया कि यह मुद्दा हमारे ऐप में रेंग रहा था - 'Foo.where (बार:' fubar ')' और 'Foo.where (बार:' fubar ') के बीच का अंतर। सभी' पूरी तरह से अलग w/r है/टी कैशिंग, और ऐसा कुछ जो आसानी से और संक्षेप में आपके कोडबेस में फिसल सकता है। यदि आप कैशिंग पर भरोसा करते हैं तो नियमित रूप से जांचें और जांचें। –

0

का उपयोग

User.where("status = 1").limit(1000).all 

काम करना चाहिए।

2

Rails.cache.fetch कैश वास्तव में ब्लॉक का मूल्यांकन करता है।

 User.where('status = 1').limit(1000) 

सिर्फ एक गुंजाइश है, तो क्या कैश की गई हो जाता है बस ActiveRecord :: रिलेशन वस्तु है, क्वेरी यानी, लेकिन उसके परिणाम (क्योंकि क्वेरी अभी तक निष्पादित नहीं किया गया है)।

आप कुछ उपयोगी कैश हो चाहते हैं, आपको लगता है कि रेल 4 पर, all की लोडिंग के लिए मजबूर नहीं है कर

User.where('status = 1').limit(1000).all 

नोट द्वारा उदाहरण के लिए, ब्लॉक के अंदर क्वेरी के निष्पादन के लिए मजबूर करने की जरूरत है संबंध - का उपयोग to_a बजाय

3

चयनित उत्तर के अतिरिक्त: रेल 4+ के लिए आपको load का उपयोग all के दायरे के परिणाम प्राप्त करने के लिए करना चाहिए।

+0

'User.find (1) .load' मुझे 'ArgumentError देता है: रेल 4.1.15 पर तर्कों की गलत संख्या (0, अपेक्षित 1..2)' – Kelseydh

संबंधित मुद्दे