Chapter 26. Visitor Counter

Remember back in the good ol’ days of the Internet, when no website was complete without a little “you are visitor number 32” thingy? Ahh, those were the good times! Let’s re-create that wonderful experience in Yesod!

Now, if we wanted to do this properly, we’d store this information in some kind of persistent storage layer, like a database, so that the information could be shared across multiple horizontally scaled web servers and would survive an app restart.

But our goal here isn’t to demonstrate good practice (after all, if it was about good practice, I wouldn’t be demonstrating a visitor counter, right?). Instead, this is meant to provide a simple example of sharing some state among multiple handlers. A real-world use case would be caching information across requests. Just remember that when you use the technique shown here, you need to be careful about multiple app servers and app restarts.

The technique is simple: we create a new field in the foundation data type for a mutable reference to some data, and then access it in each handler. The technique is so simple, it’s worth just diving into the code:

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes       #-}
{-# LANGUAGE TemplateHaskell   #-}
{-# LANGUAGE TypeFamilies      #-}
import           Data.IORef
import           Yesod

data App = App
    { visitors :: IORef Int
    }

mkYesod "App" [parseRoutes|
/ HomeR GET
|]

instance Yesod App

getHomeR :: Handler Html
getHomeR = do
    visitorsRef <- fmap visitors getYesod
    visitors

Get Developing Web Apps with Haskell and Yesod, 2nd Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.