I want to write my database access code for a Snap application in a way that makes the queries easy to test from the ghci
repl, while also working within the Snap context. My solution so far is to define a HasPostgres instance for IO and to write all my DB access functions following the pattern of allUsers
in the code snippet below. Am I doing this correctly?
{-# LANGUAGE OverloadedStrings #-}
module Database where
import Core
import Control.Applicative
import Database.PostgreSQL.Simple.FromRow (field, fromRow)
import Database.PostgreSQL.Simple.ToRow (toRow)
import Database.PostgreSQL.Simple.ToField (toField)
import Snap.Snaplet.PostgresqlSimple
import Data.Pool
import qualified Database.PostgreSQL.Simple as P
import Data.Text (Text)
import qualified Data.Text as T
import Control.Monad.CatchIO
instance FromRow User where
fromRow = User <$> field <*> field
instance ToRow User where
toRow (User a b) = [toField a, toField b]
allUsers :: (HasPostgres m) => m [User]
allUsers = query_ "SELECT user_id, email from users"
instance HasPostgres IO where
getPostgresState = do
let stripes = 1
let idle = 5
let resources = 20
let ci = P.ConnectInfo "localhost" 5432 "choi" "" "testDatabase"
pool <- createPool (P.connect ci) P.close stripes (realToFrac (idle :: Double)) resources
return $ Postgres pool