kolam
kolam

Reputation: 741

Yesod - Extract session data (non-String), store it and use it

Hi there.

Here is the code I'm trying to make work :

getGameR :: Handler Html
getGameR = do
    sess <- getSession
    defaultLayout $ do
        setTitle "Game"
        $(widgetFile "hamletFile")
    where
        person = read $ fromJust $ Map.lookup "person" sess :: Person

data Person = Person
    {
        name :: Text
    }
    deriving (Show, Read)


The error is the following:

Handler/MyHandler.hs:87:56: Not in scope: `sess'


What I'm trying to do, is to extract data from Yesod Session (data of type Person) and store it inside 'person', to be able to use it inside the hamlet file.

Is there a way to get around that error?

If it's not possible, can you suggest another way around?

Thanks in advance.

Upvotes: 0

Views: 404

Answers (2)

lambdas
lambdas

Reputation: 4090

If you just want to lookup single value, consider using lookupSession instead. Also, fromJust throws exception if key is not in session, you might use fromMaybe:

getGameR :: Handler Html
getGameR = do
    mbPersonName <- lookupSession "person"
    let defaultPerson = Person "anonymous"
    let person = fromMaybe defaultPerson (readMaybe .unpack =<< mbPersonName) :: Person
    defaultLayout $ do
        setTitle "Game"
        $(widgetFile "hamletFile")

Here is my helpers for dealing with session:

import Text.Read (readMaybe)
import Data.Maybe (fromMaybe)

readSession :: Read a => Text -> Handler (Maybe a)
readSession name = do
    textValue <- lookupSession name
    return (readMaybe . unpack =<< textValue)

readSessionDef :: Read a => a -> Text -> Handler a
readSessionDef def name =  do
    mbValue <- readSession name
    return $ fromMaybe def mbValue

readSession reads anything that can be readden and returns a Maybe. readSessionDef returns default value if such key is not present in session:

getGameR :: Handler Html
getGameR = do
    person <- readSessionDef (Person "anonymous") "person"
    defaultLayout $ do
        setTitle "Game"
        $(widgetFile "hamletFile")

Upvotes: 1

duplode
duplode

Reputation: 34378

sess is local to the do block, and thus it is not in scope in the person definition. As far as that error goes, using let inside the do block should be enough:

getGameR :: Handler Html
getGameR = do
    sess <- getSession
    let person = read $ fromJust $ Map.lookup "person" sess :: Person
    defaultLayout $ do
        setTitle "Game"
        $(widgetFile "hamletFile")

Upvotes: 4

Related Questions