2015-06-04 19 views
5

Rails uygulamasında düşük düzeyde önbellekleme yapmak için Redis'i kullanmak istiyorum. Bir denetleyici olarak Normalde bize bu tüm kitapları almak için:Koleksiyon için düşük seviye önbellekleme

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

Ve manzarası yineler bunun üzerinde:

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

Şimdi tam aynı sonuç ama sonra önbelleğe istiyorum. Redis kurulumum var ve çalışıyor. Yani bunun gibi denetleyici bir cached_books yöntemi kullanmalısınız:

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

Ve olduğu gibi görünüm bırakmak veya görünümde book.cached_title ve book.cached_author kullanıp olduğu gibi denetleyicisi bırakın?

yöntemi, Book modelinde nasıl görünüyor? Ben dışında bırakmak şimdilik stratejiler sona ama belli onlar orada olması gerekiyor kolay anlaşılması için

class Book < ActiveRecord::Base 
    ... 

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

.

+0

Ben Sadece kontrol modelleri – apneadiving

+0

yılında önbelleğe alma eklemek olmaz: //guides.rubyonrails (http: [önbelleğe alma konusunda rehber] okudun .org/caching_with_rails.html)? – zwippie

+0

Tabii ama bir koleksiyonu için özel model önbelleğe alma için kapsamlı bir açıklama için – John

cevap

5

Yani böyle denetleyicisi bir cached_books yöntemi kullanmalısınız:

Evet, yapabilirsiniz. Bazı tuhaflıklar olsa da, farkında olmalısınız. Book, ActiveRecord. Eğer (sadece örn Book.all veya Book.something çağırdığınızda bile Book.order(:title) temelde Book s dizisi (gereksiz sorguları ateş bu sarıcı önler, güçlendirici perfomance) için sarıcı olan, sana bir ActiveRecord::Relation döndürür.

kaydedemiyor Redis. Say bir sorgunun tüm sonuç, sen mesela

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

modeli özelliklerine sahip karma bir dizinin bir JSON dizesi, kaydedebilir Ve

gibi o zaman can 'şifresini' diziye bu şey sonra. bir şey
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 

Ayrıca, önbellek içine koymadan önce nitelikleri serileştirmeniz gerekecek.

Tamam, şimdi önbelleğe alınmış bir koleksiyonu order çağrı yapamazsınız rağmen bunu bir düz dizidir olarak (eğer sort çağırabilir, aynı verilerle görünümünde iterated koleksiyonları var, ama fikir etmektir önbellek zaten sıralanmış veri).

Peki ... buna değer mi? Aslında, gerçekten değil. Bu parçayı önbelleğe almanız gerekiyorsa - muhtemelen en iyi yol, oluşturulmuş bir sayfayı değil, bir sorgu sonucunu önbelleğe almaktır.

cached_title ve cached_author kullanıyor musunuz - bu iyi bir soru. Her şeyden önce, cached_title'un ne olduğuna bağlı. Bir dize ise - önbelleğe alabileceğiniz bir şey yok. DB isteğiyle Book alırsınız veya önbellekten Book alırsınız - herhangi bir şekilde title sunulacaktır, çünkü bu basit bir türdür. Ama author'a daha yakından bakalım. Büyük olasılıkla başka bir modele Author bir ilişki olacak ve bu önbellek mükemmel uyum için uygun bir yer.Kitabın içindeki author yöntemi yeniden tanımlamak (veya yeni tanımlar ve Raylar gelecekte karmaşık sorgular olabilir kötü etkilerinden kaçınmak) ve önbellek olmadığını görebiliriz. Varsa, önbelleği geri verin. Değilse - DB'yi sorgulayın, sonucu önbelleğe kaydedin ve geri gönderin.

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 

Veya daha az elverişli, ama daha "güvenli":

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

teşekkürler arıyorum, bu benim için çok kullanışlıdır! – John

İlgili konular