2015-06-04 7 views
5

मैं अपने रेल ऐप में कुछ निम्न स्तर के कैशिंग करने के लिए रेडिस का उपयोग करना चाहता हूं। इस परसंग्रह के लिए निम्न स्तर कैशिंग

class BooksController < ApplicationController 
    def index 
    @books = Book.order(:title) 
    end 
end 

और दृश्य दोहराता: एक नियंत्रक में मैं सामान्य रूप से हमें यह सब किताबें पाने के लिए

<ul> 
    - @books.each do |book| 
    <li>= "#{book.title} - #{book.author}"</li> 
</ul> 

अब मैं ठीक उसी परिणाम है, लेकिन फिर कैश्ड चाहते हैं। मेरे पास रेडिस सेटअप और चल रहा है। तो मैं इस तरह नियंत्रक में एक cached_books विधि का उपयोग करना चाहिए:

@books = Book.cached_books.order(:title) 

और दृश्य से बाहर निकलने के रूप में यह है, या ध्यान में रखते हुए book.cached_title और book.cached_author का उपयोग करें और नियंत्रक वैसा ही छोड़ दें?

और विधि Book मॉडल में कैसे दिखती है?

class Book < ActiveRecord::Base 
    ... 

    def cached_books 
    Rails.cache.fetch([self, "books"]) { books.to_a } 
    end 
end 

सादगी के लिए मैं अब के लिए समय सीमा समाप्त रणनीतियों को छोड़ देता हूं, लेकिन स्पष्ट रूप से उन्हें वहां रहने की आवश्यकता है।

+0

मैं मॉडल – apneadiving

+0

बस जाँच में कैशिंग जोड़ने wouldnt: आप पढ़ी (http [के बारे में कैशिंग गाइड]: //guides.rubyonrails .org/caching_with_rails.html)? – zwippie

+0

निश्चित रूप से, लेकिन मैं संग्रह के लिए विशिष्ट मॉडल कैशिंग की तलाश कर रहा हूं – John

उत्तर

5

तो मैं इस तरह नियंत्रक में एक cached_books विधि का उपयोग करना चाहिए:

हाँ, आप कर सकते हैं। यद्यपि कुछ गठिया हैं, आपको अवगत होना चाहिए। BookActiveRecord है। जब आप Book.something फोन (जैसे Book.all, या बस भी Book.order(:title) तो यह आपको एक ActiveRecord::Relation देता है, जो मूल रूप से Book रों की सरणी (इस आवरण अनावश्यक प्रश्नों फायरिंग की रोकता है, बढ़ाने कार्यक्षमता) के लिए आवरण है।

आप नहीं बचा सकता Redis। कहो में एक प्रश्न के पूरे परिणाम, आप मॉडल विशेषताओं के साथ हैश की एक सरणी के JSON स्ट्रिंग, जैसे

[{ 
    id: 1, 
    title: 'How to make a sandwich", 
    author: 'Mr. cooker' 
}, { 
    id: 2, 
    title: 'London's Bridge', 
    author: 'Fergie' 
}] 

बचा सकते हैं और फिर आप कर सकते हैं 'डिक्रिप्ट' सरणी में इस बात के बाद।

तरह
def cached_books(key) 
    # I suggest you to native wrapper 
    if result = $redis.hget 'books_cache', key 
    result.map do { |x| Book.new(x) } 
    end 
end 

और साथ ही, आपको कैश में डालने से पहले गुणों को क्रमबद्ध करना होगा।

ठीक है, अब आप संग्रह है जो एक ही डेटा के साथ ध्यान में रखते हुए दोहराया जा सकता है, हालांकि आप एक कैश्ड संग्रह पर order फोन नहीं कर सकते हैं के रूप में यह एक सादे सरणी है (आप sort कह सकते है,, लेकिन यह विचार करने के लिए है कैश पहले से ही क्रमबद्ध डेटा)।

अच्छा ... क्या यह इसके लायक है? असल में, वास्तव में नहीं। यदि आपको इस टुकड़े को कैश करने की आवश्यकता है - शायद, एक प्रस्तुत पृष्ठ कैश करने का सबसे अच्छा तरीका है, न कि क्वेरी परिणाम।

क्या आपको cached_title और cached_author का उपयोग करना चाहिए - यह अच्छा सवाल है। सबसे पहले, यह cached_title पर निर्भर करता है। यदि यह एक स्ट्रिंग है - तो कुछ भी नहीं है जिसे आप कैश कर सकते हैं। आपको डीबी अनुरोध के माध्यम से Book मिलता है, या आपको Book कैश से मिलता है - किसी भी तरह से title इसमें प्रस्तुत किया जाएगा, क्योंकि यह एक साधारण प्रकार है। लेकिन चलिए author के करीब देखें। सबसे अधिक संभावना है कि यह किसी अन्य मॉडल Author से संबंधित होगा और यह वह स्थान है जहां कैश पूरी तरह से उपयुक्त है।आप पुस्तक के अंदर author विधि को फिर से परिभाषित कर सकते हैं (या नया परिभाषित कर सकते हैं और भविष्य में जटिल प्रश्नों में रेल के खराब प्रभाव से बच सकते हैं) और देखें कि कैश है या नहीं। यदि हां, तो कैश वापस करें। यदि नहीं - डीबी से पूछताछ करें, परिणाम कैश में सहेजें और इसे वापस करें।

def author 
    Rails.cache.fetch("#{author_id}/info", expires_in: 12.hours) do 
    # block executed if cache is not founded 
    # it's better to alias original method and call it here 
    #instead of directly Author.find call though 
    Author.find(author_id) 
    end 
end 

या कम सुविधाजनक है, लेकिन अधिक "सुरक्षित":

def cached_author 
    Rails.cache.fetch("#{author_id}/info", expires_in: 12.hours) do 
    author 
    end 
end 
+0

व्यापक स्पष्टीकरण के लिए धन्यवाद, यह मेरे लिए बहुत उपयोगी है! – John

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