2015-11-11 4 views
7

Ich versuche, die cached Funktion zu verwenden, um mehr db-Abfragen in verschiedenen Widgets und Handler zu verhindern:Wie kann man pro Cachespeicherung von Yesod pro Anfrage arbeiten?

newtype CachedBobId key 
    = CachedBobId { unCachedBobId :: key } 
    deriving Typeable 

getBob' :: Handler BobId 
getBob' = do 
    uncle <- runInputGet $ ireq textField "bobsuncle" 
    (Entity bob _) <- runDB $ getBy404 $ UniqueBob uncle 
    return bob 

getBob :: Handler BobId 
getBob = do 
    a <- getBob' 
    let b = return $ CachedBobId a 
    c <- cached b 
    return $ unCachedBobId c 

Und in einem Widget irgendwo:

renderDerp :: Widget 
renderDerp = do 
    --these are used in the shakespeare files 
    lolBob <- handlerToWidget $ getBob 
    nutherBob <- handlerToWidget $ getBob 
    $(widgetFile "test") 

Dies kompiliert, aber die Abfrage die bekommen Die ID wird immer noch mehrfach ausgeführt.

Was mache ich falsch? Oder gibt es einen besseren Weg, nur einmal Bob zu bekommen und ihn in jedem Handler und Widget zu benutzen?

+0

Ich habe Code in der Frage nicht wirklich gelesen (da ich auch ein Problem mit 'cached' hatte). Jemand wird wirklich leicht 200 Punkte bekommen. – Cthulhu

Antwort

3

Ich bin ziemlich neu in Jessod, aber ich denke, man muss nur zwicken getBob

getBob :: Handler BobId 
getBob = unCachedBobId <$> cached (CachedBobId <$> getBob') 

Das Problem ist, dass Ihre aktuelle getBob Funktion startet seinen do Block mit a <- getBob'. Denken Sie daran, dass ein do Block Sequenzen monadischen Aktionen, so dass Sie am Ende getBob' ersten Aufruf jedes Mal, wenn getBob aufgerufen wird. In einer ironischen Wendung, nachdem Sie dies getan haben, erstellen Sie eine zwischengespeicherte Version eines Handlers, die zurückgibt, was Sie gerade von getBob' bekommen haben, aber am Ende diese zwischengespeicherte Version genau einmal abfragen (gleich danach mit c <- cached b), dann fällt es einfach aus der Umfang und der Müllsammler bekommt es.

In der Lösung, die ich oben präsentiere, wickeln Sie was auch immer getBob' gibt Sie in CachedBobId. Dann übergeben Sie diesen Handler CachedBobId <$> getBob' :: Handler (CachedBobId BobId) an cached, die Ihnen einen anderen Handler cached (CachedBobId <$> getBob') des gleichen Typs aber mit Caching zurückgibt. Schließlich extrahieren Sie, was auch immer der zwischengespeicherte Handler Ihnen gibt, um eine Handler BobId zurückzubekommen.