A bunch of scaffolding changes

This commit is contained in:
Michael Snoyman 2011-12-30 13:29:24 +02:00
parent 61f0c26e9f
commit a1b051ccca
13 changed files with 41 additions and 37 deletions

View File

@ -55,13 +55,13 @@ fromArgs = fromArgsExtra (const $ const $ return ())
-- | Same as 'fromArgs', but allows you to specify how to parse the 'appExtra' -- | Same as 'fromArgs', but allows you to specify how to parse the 'appExtra'
-- record. -- record.
fromArgsExtra :: (DefaultEnv -> Value -> IO extra) fromArgsExtra :: (DefaultEnv -> Object -> Parser extra)
-> IO (AppConfig DefaultEnv extra) -> IO (AppConfig DefaultEnv extra)
fromArgsExtra = fromArgsWith defaultArgConfig fromArgsExtra = fromArgsWith defaultArgConfig
fromArgsWith :: (Read env, Show env) fromArgsWith :: (Read env, Show env)
=> ArgConfig => ArgConfig
-> (env -> Value -> IO extra) -> (env -> Object -> Parser extra)
-> IO (AppConfig env extra) -> IO (AppConfig env extra)
fromArgsWith argConfig getExtra = do fromArgsWith argConfig getExtra = do
args <- cmdArgs argConfig args <- cmdArgs argConfig
@ -72,7 +72,7 @@ fromArgsWith argConfig getExtra = do
[] -> error $ "Invalid environment: " ++ environment args [] -> error $ "Invalid environment: " ++ environment args
let cs = (configSettings env) let cs = (configSettings env)
{ csLoadExtra = getExtra { csParseExtra = getExtra
} }
config <- loadConfig cs config <- loadConfig cs
@ -103,7 +103,7 @@ data ConfigSettings environment extra = ConfigSettings
-- environment. Usually, you will use 'DefaultEnv' for this type. -- environment. Usually, you will use 'DefaultEnv' for this type.
csEnv :: environment csEnv :: environment
-- | Load any extra data, to be used by the application. -- | Load any extra data, to be used by the application.
, csLoadExtra :: environment -> Value -> IO extra , csParseExtra :: environment -> Object -> Parser extra
-- | Return the path to the YAML config file. -- | Return the path to the YAML config file.
, csFile :: environment -> IO FilePath , csFile :: environment -> IO FilePath
-- | Get the sub-object (if relevant) from the given YAML source which -- | Get the sub-object (if relevant) from the given YAML source which
@ -115,7 +115,7 @@ data ConfigSettings environment extra = ConfigSettings
configSettings :: Show env => env -> ConfigSettings env () configSettings :: Show env => env -> ConfigSettings env ()
configSettings env0 = ConfigSettings configSettings env0 = ConfigSettings
{ csEnv = env0 { csEnv = env0
, csLoadExtra = \_ _ -> return () , csParseExtra = \_ _ -> return ()
, csFile = \_ -> return "config/settings.yml" , csFile = \_ -> return "config/settings.yml"
, csGetObject = \env v -> do , csGetObject = \env v -> do
envs <- envs <-
@ -161,7 +161,7 @@ configSettings env0 = ConfigSettings
-- --
loadConfig :: ConfigSettings environment extra loadConfig :: ConfigSettings environment extra
-> IO (AppConfig environment extra) -> IO (AppConfig environment extra)
loadConfig (ConfigSettings env loadExtra getFile getObject) = do loadConfig (ConfigSettings env parseExtra getFile getObject) = do
fp <- getFile env fp <- getFile env
mtopObj <- decodeFile fp mtopObj <- decodeFile fp
topObj <- maybe (fail "Invalid YAML file") return mtopObj topObj <- maybe (fail "Invalid YAML file") return mtopObj
@ -173,14 +173,14 @@ loadConfig (ConfigSettings env loadExtra getFile getObject) = do
let mssl = lookupScalar "ssl" m let mssl = lookupScalar "ssl" m
let mhost = lookupScalar "host" m let mhost = lookupScalar "host" m
let mport = lookupScalar "port" m mport <- parseMonad (\x -> x .: "port") m
let mapproot = lookupScalar "approot" m let mapproot = lookupScalar "approot" m
extra <- loadExtra env obj extra <- parseMonad (parseExtra env) m
-- set some default arguments -- set some default arguments
let ssl = maybe False toBool mssl let ssl = maybe False toBool mssl
port' <- safeRead "port" $ fromMaybe (if ssl then "443" else "80") mport let port' = fromMaybe (if ssl then 443 else 80) mport
approot <- case (mhost, mapproot) of approot <- case (mhost, mapproot) of
(_ , Just ar) -> return ar (_ , Just ar) -> return ar
@ -212,14 +212,6 @@ loadConfig (ConfigSettings env loadExtra getFile getObject) = do
addPort False 80 = "" addPort False 80 = ""
addPort _ p = T.pack $ ':' : show p addPort _ p = T.pack $ ':' : show p
-- | Returns 'fail' if read fails
safeRead :: Monad m => String -> Text -> m Int
safeRead name' t = case reads s of
(i, _):_ -> return i
[] -> fail $ concat ["Invalid value for ", name', ": ", s]
where
s = T.unpack t
-- | Loads the configuration block in the passed file named by the -- | Loads the configuration block in the passed file named by the
-- passed environment, yeilds to the passed function as a mapping. -- passed environment, yeilds to the passed function as a mapping.
-- --
@ -228,12 +220,12 @@ safeRead name' t = case reads s of
withYamlEnvironment :: Show e withYamlEnvironment :: Show e
=> FilePath -- ^ the yaml file => FilePath -- ^ the yaml file
-> e -- ^ the environment you want to load -> e -- ^ the environment you want to load
-> (Value -> IO a) -- ^ what to do with the mapping -> (Value -> Parser a) -- ^ what to do with the mapping
-> IO a -> IO a
withYamlEnvironment fp env f = do withYamlEnvironment fp env f = do
mval <- decodeFile fp mval <- decodeFile fp
case mval of case mval of
Nothing -> fail $ "Invalid YAML file: " ++ show fp Nothing -> fail $ "Invalid YAML file: " ++ show fp
Just (Object obj) Just (Object obj)
| Just v <- M.lookup (T.pack $ show env) obj -> f v | Just v <- M.lookup (T.pack $ show env) obj -> parseMonad f v
_ -> fail $ "Could not find environment: " ++ show env _ -> fail $ "Could not find environment: " ++ show env

View File

@ -30,7 +30,7 @@ library
, shakespeare-css >= 0.10.5 && < 0.11 , shakespeare-css >= 0.10.5 && < 0.11
, shakespeare-js >= 0.10.4 && < 0.11 , shakespeare-js >= 0.10.4 && < 0.11
, template-haskell , template-haskell
, yaml >= 0.5 && < 0.6 , yaml >= 0.5.1.1 && < 0.6
, unordered-containers , unordered-containers
if !os(windows) if !os(windows)

View File

@ -84,7 +84,7 @@ scaffold = do
let runMigration = let runMigration =
case backend of case backend of
MongoDB -> "" MongoDB -> ""
_ -> "\n Database.Persist.Base.runPool dbconf (runMigration migrateAll) p" _ -> "\n Database.Persist.Store.runPool dbconf (runMigration migrateAll) p"
let importMigration = let importMigration =
case backend of case backend of

View File

@ -37,7 +37,7 @@ with~sitearg~ :: AppConfig DefaultEnv Extra -> Logger -> (Application -> IO ())
with~sitearg~ conf logger f = do with~sitearg~ conf logger f = do
s <- staticSite s <- staticSite
dbconf <- withYamlEnvironment "config/~dbConfigFile~.yml" (appEnv conf) dbconf <- withYamlEnvironment "config/~dbConfigFile~.yml" (appEnv conf)
$ either error return . Database.Persist.Store.loadConfig Database.Persist.Store.loadConfig
Database.Persist.Store.withPool (dbconf :: Settings.PersistConfig) $ \p -> do~runMigration~ Database.Persist.Store.withPool (dbconf :: Settings.PersistConfig) $ \p -> do~runMigration~
let h = ~sitearg~ conf logger s p let h = ~sitearg~ conf logger s p
defaultRunner (f . logWare) h defaultRunner (f . logWare) h
@ -54,6 +54,6 @@ withDevelAppPort =
toDyn $ defaultDevelAppWith loader with~sitearg~ toDyn $ defaultDevelAppWith loader with~sitearg~
where where
loader = loadConfig (configSettings Development) loader = loadConfig (configSettings Development)
{ csLoadExtra = loadExtra { csParseExtra = parseExtra
} }

View File

@ -31,7 +31,7 @@ import qualified Settings
import qualified Data.ByteString.Lazy as L import qualified Data.ByteString.Lazy as L
import qualified Database.Persist.Store import qualified Database.Persist.Store
import Database.Persist.~importGenericDB~ import Database.Persist.~importGenericDB~
import Settings (widgetFile, Extra) import Settings (widgetFile, Extra (..))
import Model import Model
import Text.Jasmine (minifym) import Text.Jasmine (minifym)
import Web.ClientSession (getKey) import Web.ClientSession (getKey)
@ -88,6 +88,7 @@ instance Yesod ~sitearg~ where
encryptKey _ = fmap Just $ getKey "config/client_session_key.aes" encryptKey _ = fmap Just $ getKey "config/client_session_key.aes"
defaultLayout widget = do defaultLayout widget = do
y <- getYesod
mmsg <- getMessage mmsg <- getMessage
-- We break up the default layout into two components: -- We break up the default layout into two components:

View File

@ -9,7 +9,7 @@ module Settings
, staticRoot , staticRoot
, staticDir , staticDir
, Extra (..) , Extra (..)
, loadExtra , parseExtra
) where ) where
import Prelude import Prelude
@ -20,6 +20,7 @@ import Yesod.Default.Config
import qualified Yesod.Default.Util import qualified Yesod.Default.Util
import Data.Text (Text) import Data.Text (Text)
import Data.Yaml import Data.Yaml
import Control.Applicative
-- | Which Persistent backend this site is using. -- | Which Persistent backend this site is using.
type PersistConfig = ~configPersist~ type PersistConfig = ~configPersist~
@ -59,7 +60,9 @@ widgetFile = Yesod.Default.Util.widgetFileNoReload
#endif #endif
data Extra = Extra data Extra = Extra
{ extraCopyright :: Text
}
loadExtra :: DefaultEnv -> Value -> IO Extra parseExtra :: DefaultEnv -> Object -> Parser Extra
loadExtra _ _ = return Extra parseExtra _ o = Extra <$> o .: "copyright"

View File

@ -1,6 +1,7 @@
Default: &defaults Default: &defaults
host: "localhost" host: "localhost"
port: 3000 port: 3000
copyright: Insert copyright statement here
Development: Development:
<<: *defaults <<: *defaults

View File

@ -1,8 +1,8 @@
import Prelude (IO) import Prelude (IO)
import Yesod.Default.Config (fromArgsExtra) import Yesod.Default.Config (fromArgsExtra)
import Yesod.Default.Main (defaultMain) import Yesod.Default.Main (defaultMain)
import Settings (loadExtra) import Settings (parseExtra)
import Application (with~sitearg~) import Application (with~sitearg~)
main :: IO () main :: IO ()
main = defaultMain (fromArgsExtra loadExtra) with~sitearg~ main = defaultMain (fromArgsExtra parseExtra) with~sitearg~

View File

@ -1,8 +1,8 @@
!!! !!!
<html> <html>
<head <head>
<title>#{pageTitle pc} <title>#{pageTitle pc}
^{pageHead pc} ^{pageHead pc}
<body <body>
^{pageBody pc} ^{pageBody pc}

View File

@ -1,4 +1,6 @@
$maybe msg <- mmsg $maybe msg <- mmsg
<div #message>#{msg} <div #message>#{msg}
^{widget} ^{widget}
<footer>
#{extraCopyright $ appExtra $ settings y}

View File

@ -5,7 +5,7 @@ module Application
) where ) where
import Import import Import
import Settings (loadExtra) import Settings (parseExtra)
import Settings.StaticFiles (staticSite) import Settings.StaticFiles (staticSite)
import Yesod.Default.Config import Yesod.Default.Config
import Yesod.Default.Main (defaultDevelAppWith, defaultRunner) import Yesod.Default.Main (defaultDevelAppWith, defaultRunner)
@ -38,6 +38,6 @@ withDevelAppPort =
toDyn $ defaultDevelAppWith loader with~sitearg~ toDyn $ defaultDevelAppWith loader with~sitearg~
where where
loader = loadConfig (configSettings Development) loader = loadConfig (configSettings Development)
{ csLoadExtra = loadExtra { csParseExtra = parseExtra
} }

View File

@ -19,7 +19,7 @@ import Yesod.Static (Static, base64md5, StaticRoute(..))
import Settings.StaticFiles import Settings.StaticFiles
import Yesod.Logger (Logger, logMsg, formatLogText) import Yesod.Logger (Logger, logMsg, formatLogText)
import qualified Settings import qualified Settings
import Settings (Extra, widgetFile) import Settings (Extra (..), widgetFile)
import Control.Monad.IO.Class (liftIO) import Control.Monad.IO.Class (liftIO)
import Web.ClientSession (getKey) import Web.ClientSession (getKey)
import Text.Hamlet (hamletFile) import Text.Hamlet (hamletFile)
@ -67,6 +67,7 @@ instance Yesod ~sitearg~ where
encryptKey _ = fmap Just $ getKey "config/client_session_key.aes" encryptKey _ = fmap Just $ getKey "config/client_session_key.aes"
defaultLayout widget = do defaultLayout widget = do
y <- getYesod
mmsg <- getMessage mmsg <- getMessage
-- We break up the default layout into two components: -- We break up the default layout into two components:

View File

@ -8,7 +8,7 @@ module Settings
, staticRoot , staticRoot
, staticDir , staticDir
, Extra (..) , Extra (..)
, loadExtra , parseExtra
) where ) where
import Prelude import Prelude
@ -18,6 +18,7 @@ import Yesod.Default.Config
import qualified Yesod.Default.Util import qualified Yesod.Default.Util
import Data.Text (Text) import Data.Text (Text)
import Data.Yaml import Data.Yaml
import Control.Applicative
-- | The location of static files on your system. This is a file system -- | The location of static files on your system. This is a file system
-- path. The default value works properly with your scaffolded site. -- path. The default value works properly with your scaffolded site.
@ -48,6 +49,9 @@ widgetFile = Yesod.Default.Util.widgetFileNoReload
#endif #endif
data Extra = Extra data Extra = Extra
{ extraCopyright :: Text
}
parseExtra :: DefaultEnv -> Object -> Parser Extra
parseExtra _ o = Extra <$> o .: "copyright"
loadExtra :: DefaultEnv -> Value -> IO Extra
loadExtra _ _ = return Extra