2016-05-04 7 views
2

Ich habe einen Ruby-Workflow, der wenige teure API-Aufrufe macht. Ich weiß, wir haben eine einfachere Möglichkeit, Dinge in Ruby on Rails zu cachen, haben aber kein Ruby-Juwel für Ruby-Skripte gefunden.Wie Methoden in Ruby Cache?

Was ist der einfachste und einfachste Weg zum Zwischenspeichern von Ergebnissen für eine Methode, die für eine reine Ruby-Anwendung auf Eingaben angewiesen ist?

//pseudo code 
def get_information (id) 
    user_details = expensive_api_call(id) 
    return user_details 
end 
+1

Sie wollen nicht, um die Methode cachen, sondern das Ergebnis des Methodenaufrufes. –

+3

_Sidenote_: Bitte geben Sie niemals ein Leerzeichen zwischen Funktionsnamen und Klammern ein. Dies kann (in verschiedenen Fällen) viele unerwartete Probleme verursachen. – mudasobwa

+0

Wovon du sprichst, ist [Memoisierung] (https://en.wikipedia.org/wiki/Memoization). Sie können die Ausgabe einer Methode basierend auf ihren eingehenden Parametern zwischenspeichern, wenn der aufgerufene Code immer denselben Wert für dieselbe Eingabe zurückgibt. Es gibt jedoch Nachteile beim Caching von Ergebnissen für lang andauernde Prozesse. Wenn ein Wert für eine sehr kurze Zeit verwendet wird, auch wenn er 100 Mal verwendet wird, dann nie wieder verwendet wird, aber für Tage/Wochen/Monate zwischengespeichert wird, dann verschwendet er Ressourcen, also ist es wichtig, sie zeitlich zu begrenzen und zu löschen. –

Antwort

3

Der einfachste Weg ist es, einen Hash zu verwenden:

class ApiWithCache 

    def initialize 
    @cache = {} 
    end 

    def do_thing(id) 
    expensive_api_call(id) 
    end 

    def do_thing_with_cache(id) 
    @cache[id] ||= do_thing(id) 
    end 
end 

Nun ist diese wirft einige Probleme, die Sie vielleicht schauen:

  • Ablauf der im Cache gespeicherten Daten
  • Größe des Caches (um einige Elemente nicht zu entfernen)
0

Sie können dies tun, um eine Instanz-Variable unter Verwendung eines Hash enthält, und die ||= Operator, wie in:

def initialize 
    @user_cache = {} 
    # ... 
end 

def get_information(id) 
    @user_cache[id] ||= expensive_api_call(id) 
end 

||= Mittel den Methodenaufruf auszuführen, und die Zuordnung nur durchführen, wenn der L-Wert (in diesem Fall @user_cache[id]) ist falsy (Null oder Falsch) Andernfalls wird der Wert verwendet, der bereits im Hash enthalten ist.

1

Es ist schon ziemlich leicht in reinem Rubin:

def foo(id) 
    @foo[id] ||= some_expensive_operation 
end 

Soweit Edelsteine ​​gehen - check out memoist.

+0

Das wird nicht funktionieren. Es gibt einen Parameter, also möglicherweise unterschiedliche Ergebnisse. –

+0

@pascalbetz aktualisiert. Jetzt wird es funktionieren, gegeben 'foo' ist ein Hash. – ndn

+0

Ich habe gerade eine Änderung vorgeschlagen, um '[id]' zum Fragecode hinzuzufügen, der dies verdeutlichen sollte. –

0

Sie es durch Hash globalen Variable

def get_information(id) 
    @user_details ||= {} 
    @user_details[id] ||= expensive_api_call(id) 
    return @user_details[id] 
end