2012-12-03 6 views
6

Mam stronę główną, która ma częściowe renderowanie na całej stronie. Ma również nagłówek sesji (login). Częściowa zawiera zestaw książek podzielonych na strony. Teraz chcę buforować to częściowe, ponieważ jest aktualizowana raz na tydzień.Buforowanie określonych częściowych szyn 3.0.x

  • Pytanie 1: W jaki sposób buforowania, że ​​szczególną częściowy (bez uderzania dB)?
  • Pytanie 2: Jak usunąć (wygasić) buforowaną zawartość podczas aktualizacji tego modelu książki?

Odpowiedz

8

Tutaj szuka się fragment caching, który występuje w warstwie widoku. Fragmentowanie pamięci podręcznej i wygaśnięcie przechowywanych treści jest zaskakująco łatwe. Masz listę książek, więc powiedzmy, że twój widok wygląda trochę tak:

<ul> 
    <% @books.each do |book| %> 
    <li><%= book.name %></li> 
    <% end %> 
</ul> 

Aby włączyć buforowanie tylko dla tego kawałka, po prostu zawinąć go w cache:

<% cache do %> 
    <ul> 
    <% @books.each do |book| %> 
     <li><%= book.name %></li> 
    <% end %> 
    </ul> 
<% end %> 

Oczywiście, to nie nazywa pamięci podręcznej ani nie robi z nią nic specjalnego ... podczas gdy Railsy automatycznie wybierają unikalną nazwę tego fragmentu pamięci podręcznej, nie będzie to naprawdę pomocne. Możemy zrobić lepiej. Zastosujmy technikę DHH key-based cache expiration i nadaj pamięci podręcznej nazwę związaną z jej zawartością.

<% cache ['book-list', *@books] do %> 
    <ul> 
    <% @books.each do |book| %> 
     <li><%= book.name %></li> 
    <% end %> 
    </ul> 
<% end %> 

Przekazywanie argumentów do pamięci podręcznej cache buduje klucz z dostarczonych argumentów. Ciągi są przekazywane bezpośrednio - tak więc pamięć podręczna zawsze będzie poprzedzona "listą książek". Ma to na celu zapobieganie kolizjom pamięci podręcznej z innymi miejscami, w których buforowana jest ta sama treść, ale z innym widokiem. Dla każdego członka tablicy @books, Railsy wywołają cache_key: dla obiektów ActiveRecord, to daje ciąg złożony z jego modelu, ID, i co najważniejsze, ostatnio, gdy obiekt został zaktualizowany.

Oznacza to, że po zaktualizowaniu obiektu klucz pamięci podręcznej dla tego fragmentu ulegnie zmianie. Innymi słowy, automatycznie wygasa - kiedy książka jest aktualizowana, ta instrukcja pamięci podręcznej wyszuka nieistniejący klucz, dojdzie do wniosku, że nie istnieje i zapełni go nową treścią. Stara, nieaktualna zawartość pozostanie w twoim magazynie pamięci podręcznej do czasu eksmisji z powodu ograniczeń związanych z pamięcią lub wiekiem (memcached robi to automatycznie).

Używam tej techniki w wielu aplikacjach produkcyjnych i działa wspaniale. Aby uzyskać więcej informacji, sprawdź, czy 37signals post i ogólne informacje o buforowaniu w Railsach, zobacz Ruby on Rails caching guide.

+0

+1 na splatting kolekcję @books. Nigdy o tym nie pomyślałem, zwykle pobierałbym ostatnio zaktualizowany rekord książki w całej tabeli i używałam tego – cpuguy83

+0

Powinieneś również buforować każdą książkę, aby jedna zmieniona książka nie przerwała całej pamięci podręcznej. – cpuguy83

4

„Istnieją tylko dwa twarde problemy w dziedzinie informatyki. cache unieważnianie i nazywanie rzeczy”
- Phil Karlton

buforowanie


The Rails Guide to caching jest prawdopodobnie zawsze dobry punkt wyjścia dla wbudowanego w strategii buforowania szyn ma do zaoferowania.W każdym razie tutaj jest mój bardzo łatwy podejście do buforowania

# _partial.html.erb 
<% cache(some_key, :expires_in => 1.week) do %> 
    <%# ... content %> 
<% end %> 

Teraz niektórzy some_key może być dowolny ciąg tak długo, jak to jest wyjątkowa. Ale potem znowu spróbujmy być nieco mądrzejsi i sprawmy, że klucz w jakiś sposób będzie zależał od listy książek. Powiedzmy, że faktycznie przekazujemy w tablicy books zapytanie zwrócone, a następnie wywołujemy railsy cache_key na każdym z jego wpisów i ostatecznie konstruujemy unikalny klucz dla tej kolekcji. Więc kiedy kolekcja zmienia kluczowe zmiany. To dlatego, że cache_key jest zaimplementowany w ActiveRecord::Base i tym samym jest dostępny we wszystkich modelach. Co więcej, wykorzystuje nawet sygnatury czasowe, jeśli są dostępne.

Ale potem znowu to będzie hit db za każdym razem, gdy wniosek zostanie złożony. To samo w kodzie:

# controller_method 
@weekly_books = Books.where 'condition' 

# _partial.html.erb 
<% cache(@weekly_books) do %> 
    <%# ... content %> 
<% end %> 

Aby uniknąć uderzenia db często można także buforować zapytaniu swój własny owijając połączenia:

# Book.rb 
def self.weeklies 
    Rails.cache.fetch("book_weeklies", :expires_in => 1.day) do 
    Books.where 'condition' 
    end 
end 

# controller_method 
@weekly_books = Books.weeklies 

# _partial.html.erb 
<% cache(@weekly_books) do %> 
    <%# ... content %> 
<% end %> 
+0

Problem występuje na mojej stronie głównej Książki są paginowane. Wysyłam podzielone na strony książki na częściowe. Teraz, jeśli użyję Books.weeklies, to nie da to stronicowanych rekordów. Jak to osiągnąć? –

Powiązane problemy