2010-08-30 9 views
10

मैं एक महंगी (समय लेने वाली) किसी अन्य वेब सेवा मैं बनाने की जरूरत के लिए बाहरी अनुरोध किया है, और मैं इसे कैश करने के लिए करना चाहते हैं। इसलिए मैं आवेदन नियंत्रक में निम्नलिखित रख कर इस idiom, उपयोग करने का प्रयास:मैं रूबी/रेल के साथ एक विधि कैसे कैश करते हैं?

def get_listings 
    cache(:get_listings!) 
end 

def get_listings! 
    return Hpricot.XML(open(xml_feed)) 
end 

जब मैं अपने नियंत्रक सब कुछ में get_listings! फोन शांत है, लेकिन शिकायत है कि कोई ब्लॉक दिया गया था जब मैं get_listings रेल कहते हैं। और जब मुझे लगता है कि विधि को देखने मुझे लगता है कि यह वास्तव में एक ब्लॉक उम्मीद करता है, और इसके अलावा यह है कि विधि की तरह दिखता है केवल विचारों में उपयोग के लिए है? तो मैं अनुमान लगा रहा हूं कि यद्यपि यह नहीं बताया गया था, कि उदाहरण सिर्फ छद्म कोड है।

तो मेरे सवाल का, मैं कैसे कुछ इस तरह कैश करते है? मैंने कई अन्य तरीकों की कोशिश की लेकिन इसे समझ नहीं पाया। धन्यवाद!

उत्तर

9

nruth पता चलता है, रेल 'में निर्मित कैश दुकान शायद तुम क्या चाहते है।

प्रयास करें:

def get_listings 
    Rails.cache.fetch(:listings) { get_listings! } 
end 

def get_listings! 
    return Hpricot.XML(open(xml_feed)) 
end 

लाने() निर्दिष्ट कुंजी के लिए कैश की गई मान प्राप्त करता है, या कैश करने के लिए ब्लॉक का परिणाम लिखते हैं, अगर यह मौजूद नहीं है।

डिफ़ॉल्ट रूप से, रेल कैश फ़ाइल स्टोर का उपयोग करता है, लेकिन उत्पादन वातावरण में, memcached पसंदीदा विकल्प है।

अधिक जानकारी के लिए http://guides.rubyonrails.org/caching_with_rails.html के अनुभाग 2 देखें। अपने कोड में

gem install cache_method 
require 'cache_method' 

:

11

एक में कोड दृष्टिकोण कुछ इस तरह दिखाई दे सकता है:,

def get_listings 
    @listings ||= get_listings! 
end 

def get_listings! 
    Hpricot.XML(open(xml_feed)) 
end 

जो एक प्रति अनुरोध के आधार पर परिणाम कैश होगा (अनुरोध के अनुसार नए नियंत्रक उदाहरण) ही आप को देखने के लिए पसंद कर सकते हैं ' एपीआई विकल्प के रूप में 'हेल्पर्स' को याद रखें।

आप भर में साझा करना चाहते हैं अनुरोध करता जब तक आप समवर्ती प्रोग्रामिंग में अच्छा कर रहे हैं वस्तुओं वर्ग पर डेटा सहेजने नहीं है, अपने अनुप्रयोग रूप threadsafe नहीं होगा, & सुनिश्चित करें कि धागे हस्तक्षेप नहीं करते एक दूसरे के डेटा साझा साझा चर के लिए उपयोग के साथ।

"रेल रास्ता" अनुरोध भर में कैश करने के लिए Rails.cache store है। Memcached बहुत उपयोग किया जाता है, लेकिन आप फ़ाइल या मेमोरी स्टोर अपनी जरूरतों के अनुरूप हो सकता है। यह वास्तव में इस पर निर्भर करता है कि आप कैसे तैनात कर रहे हैं और क्या आप कैश हिट, प्रतिक्रिया समय, संग्रहण (रैम) को प्राथमिकता देना चाहते हैं, या होस्ट किए गए समाधान का उपयोग करना चाहते हैं उदा। एक heroku addon।

+0

हाँ के बजाय इसका उपयोग करने के लिए, मैं निश्चित रूप से अनुरोधों के बीच इसे कैश करना चाहता हूं। मैंने इसे डेटाबेस में संग्रहीत करने और इसे मैन्युअल रूप से करने पर विचार किया था, लेकिन मुझे उम्मीद है कि ऐसा करने का एक आसान तरीका है। –

+1

शायद ActiveSupport :: कैश :: स्टोर के लिए दस्तावेज़/एपीआई पर नज़र डालें - जो आप बाद में फिट हो सकते हैं। मैंने अपने साथ काम नहीं किया है, लेकिन मुझे यकीन है कि यहां ब्लॉग पोस्ट हैं या अन्य लोग जिन्होंने इसका इस्तेमाल किया है उदा। memcached के साथ। – nruth

3

आप cache_method मणि का उपयोग कर सकते

def get_listings 
    Hpricot.XML(open(xml_feed)) 
end 
cache_method :get_listings 

आप देख सकते हैं मैं get_listings! से छुटकारा मिला।आप मैन्युअल रूप से डेटा ताज़ा करने के लिए एक तरह से की जरूरत है, मेरा सुझाव है:

def get_listings 
    Hpricot.XML(open(xml_feed)) 
end 
cache_method :get_listings, (60*60) # automatically expire cache after an hour 
+0

वैसे, आपको मणि को कॉन्फ़िगर करने के तरीके को देखने के लिए मणि दस्तावेज़ों को देखना चाहिए। संकेत: CacheMethod.config.storage = Rails.cache –

1

तुम भी cachethod मणि (https://github.com/reneklacan/cachethod)

gem 'cachethod' 

यह तो उपयोग कर सकते हैं:

def refresh 
    clear_method_cache :get_listings 
end 

यहाँ एक और tidbit है विधि के परिणाम कैश करने के लिए घातक सरल है

class Dog 
    cache_method :some_method, expires_in: 1.minutes 

    def some_method arg1 
    .. 
    end 
end 

यह तर्क स्तर कैशिंग का समर्थन करता है

0

अन्य उत्तर उत्कृष्ट हैं लेकिन यदि आप एक सरल हाथ से लुढ़का दृष्टिकोण चाहते हैं तो आप यह कर सकते हैं। अपनी कक्षा में एक नीचे की तरह एक विधि ...

def use_cache_if_available(method_name,&hard_way) 
@cached_retvals ||= {} # or initialize in constructor 
return @cached_retvals[method_name] if @cached_retvals.has_key?(method_name) 
@cached_retvals[method_name] = hard_way.call 
end 

परिभाषित इसके बाद, प्रत्येक विधि आप कैश करने के लिए आप कुछ इस तरह में विधि शरीर लपेट डाल सकते हैं चाहते हैं के लिए ...

def some_expensive_method(arg1, arg2, arg3) 
    use_cache_if_available(__method__) { 
    calculate_it_the_hard_way_here 
    } 
end 

एक बात यह है कि यह ऊपर सूचीबद्ध सबसे सरल विधि से बेहतर है कि यह एक शून्य कैश करेगा। इसमें सुविधा है कि इसे डुप्लिकेट विधियों को बनाने की आवश्यकता नहीं है। शायद मणि दृष्टिकोण क्लीनर है, यद्यपि।

0

cache_method मणि का सुझाव दिया गया था, हालांकि यह काफी भारी है। आप तर्क के बिना विधि कॉल करने की जरूरत है, समाधान बहुत सरल है:

def get_listings 
    Hpricot.XML(open(xml_feed)) 
end 
cache_method :get_listings 

नोट - यह भी कैश नहीं के बराबर है, जो केवल कारण है:

Object.class_eval do 

    def self.cache_method(method_name) 
    original_method_name = "_original_#{method_name}" 
    alias_method original_method_name, method_name 
    define_method method_name do 
     @cache ||= {} 
     @cache[method_name] = send original_method_name unless @cache.key?(method_name) 
     @cache[method_name] 
    end 
    end 

end 

तो आप इसे किसी भी कक्षा में उपयोग कर सकते हैं @cached_value ||=

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