2009-03-19 11 views
11

Czy istnieje sposób buforowania danych na żądanie w Railsach? Dla danego żądania Rails/mongrel mam wynik semi-kosztownej operacji, do której chciałbym uzyskać dostęp kilka razy później w tym żądaniu. Czy istnieje skrót, w którym mogę przechowywać i uzyskiwać dostęp do takich danych?Funkcja mieszania szyn na żądanie?

To musi być dość globalne i dostępne z widoków, kontrolerów i bibliotek, takich jak Rails.cache i I18n.

Dobrze, że poprawiam małpy, jeśli to jest potrzebne.

  • Memcached nie działa, ponieważ będzie współużytkowany z żądaniami, których nie chcę.
  • Podobnie zmienna globalna nie działa, ponieważ różne żądania dzielą te same dane, co nie jest tym, czego chcę.
  • Zmienne instancji nie działają, ponieważ chcę uzyskać dostęp do danych z różnych klas.
+0

Mówisz, że ma to być współużytkowane przez wniosków (po kulach 1), ale również, że nie chcesz wnioski dzieląc go (kula 2). Chyba wiem, co masz na myśli, ale powinieneś to wyjaśnić. –

+0

W podpunkcie 1 mówię, że nie chcę, aby był on wspólny dla żądań. –

Odpowiedz

4

Wypróbuj PerRequestCache. Ukradłem projekt z SQL Query Cache.

skonfigurować go w config/environment.rb z:

config.middleware.use PerRequestCache 

następnie używać go z:

PerRequestCache.fetch(:foo_cache){ some_expensive_foo } 
+0

Zgodnie z sugestią, nie jest to bezpieczne dla wątków. Właśnie skończyłem ukrywać rzeczy bezpośrednio w SQL Query Cache. To hack, ale działa. –

1

Globalne zmienne są złe. Sprawdź, jak przekazać dane, które chcesz, tam, gdzie chcesz z nich korzystać.

+5

To nie zawsze jest praktyczne. Jak wspomniałem, Rails ma globalne obiekty, takie jak Rails.cache i I18n. –

0

Czy rozważałeś flash? Używa sesji, ale jest automatycznie czyszczony.

-3

app/models/my_cacher.rb

class MyCacher 
    def self.result 
    @@result ||= begin 
     # do expensive stuff 
     # and cache in @@result 
    end 
    end 
end 

|| = składnia zasadniczo oznacza "wykonaj następujące czynności, jeśli @@ wynik jest zerowa" (to jeszcze nie jest ustawiona do niczego). Po prostu upewnij się, że ostatnia linia w bloku początkowym/końcowym zwraca wynik.

Następnie w widokach/modeli/cokolwiek byś tylko odwołują się do funkcji, gdy jest to potrzebne:

MyCacher.result 

To będzie buforować kosztowne działania na czas trwania wniosku.

+4

To będzie buforowane przez całe życie instancji aplikacji (wiele żądań) w trybie produkcyjnym. – cwninja

0

Memoisation?

Zgodnie z this railscast jest przechowywany na żądanie.

+2

Memoizacja w metodzie klasy będzie buforować przez cały czas. Pamięć na instancję będzie buforować przez cały okres istnienia tej instancji. Nadmierne buforowanie na klasach zapycha pamięć. Zdjąłem puszki produkcyjne, popełniając ten błąd. – cwninja

4

Istnieje również request_store gem.Z dokumentacji:

Dodaj tę linię do Gemfile danej aplikacji:

gem 'request_store' 

i użyć tego kodu do przechowywania i pobierania danych (ograniczonych do życzenie):

# Set 
RequestStore.store[:foo] = 0 

# Get 
RequestStore.store[:foo] 
+0

Klejnot w zasadzie rozwiązuje cały problem. Dodałem kilka instrukcji użytkowania, ale zasadniczo nie ma w tym nic więcej. –

+0

Nie należy używać tego klejnotu z serwerem z gwintem, takim jak Thin lub Puma. – Papipo

+0

@Papipo Dokumentacja tego klejnotu jawnie definiuje się jako funkcjonalna alternatywa dla 'Thread.current' dla serwerów z wątkami, takich jak Thin i Puma. – James

1

jednym z najbardziej popularną opcją jest użycie klejnotu request_store, który umożliwia dostęp do globalnego sklepu z dowolnej części kodu. Używa ona Thread.current do przechowywania danych i zajmuje się czyszczeniem danych po każdym żądaniu.

RequestStore[:items] = [] 

Należy pamiętać jednak, ponieważ używa Thread.current, to nie będzie działać prawidłowo w środowisku wielowątkowym, gdzie masz więcej niż jeden wątek na żądanie.

Aby obejść ten problem, zaimplementowałem magazyn, który może być współdzielony między wątkami dla tego samego żądania. To się nazywa request_store_rails, jest bezpieczny wątku, a użycie jest bardzo podobna:

RequestLocals[:items] = [] 
Powiązane problemy