Commented the scaffolded site

This commit is contained in:
Michael Snoyman 2010-09-20 10:44:42 +02:00
parent d741e335c4
commit 7547aaa8fd
9 changed files with 153 additions and 31 deletions

View File

@ -4,6 +4,8 @@ import System.IO
import System.Directory import System.Directory
import qualified Data.ByteString.Char8 as S import qualified Data.ByteString.Char8 as S
import Language.Haskell.TH.Syntax import Language.Haskell.TH.Syntax
import Data.Time (getCurrentTime, utctDay, toGregorian)
import Control.Applicative ((<$>))
main :: IO () main :: IO ()
main = do main = do
@ -37,6 +39,9 @@ main = do
putStrLn "That's it! I'm creating your files now..." putStrLn "That's it! I'm creating your files now..."
let fst3 (x, _, _) = x
year <- show . fst3 . toGregorian . utctDay <$> getCurrentTime
let writeFile' fp s = do let writeFile' fp s = do
putStrLn $ "Generating " ++ fp putStrLn $ "Generating " ++ fp
writeFile (dir ++ '/' : fp) s writeFile (dir ++ '/' : fp) s

View File

@ -10,16 +10,26 @@ import Yesod.Helpers.Static
import Yesod.Helpers.Auth import Yesod.Helpers.Auth
import Database.Persist.GenericSql import Database.Persist.GenericSql
-- Import all relevant handler modules here.
import Handler.Root import Handler.Root
-- This line actually creates our YesodSite instance. It is the second half
-- of the call to mkYesodData which occurs in ~sitearg~.hs. Please see
-- the comments there for more details.
mkYesodDispatch "~sitearg~" resources~sitearg~ mkYesodDispatch "~sitearg~" resources~sitearg~
-- Some default handlers that ship with the Yesod site template. You will
-- very rarely need to modify this.
getFaviconR :: Handler () getFaviconR :: Handler ()
getFaviconR = sendFile "image/x-icon" "favicon.ico" getFaviconR = sendFile "image/x-icon" "favicon.ico"
getRobotsR :: Handler RepPlain getRobotsR :: Handler RepPlain
getRobotsR = return $ RepPlain $ toContent "User-agent: *" getRobotsR = return $ RepPlain $ toContent "User-agent: *"
-- This function allocates resources (such as a database connection pool),
-- performs initialization and creates a WAI application. This is also the
-- place to put your migrate statements to have automatic database
-- migrations handled by Yesod.
with~sitearg~ :: (Application -> IO a) -> IO a with~sitearg~ :: (Application -> IO a) -> IO a
with~sitearg~ f = Settings.withConnectionPool $ \p -> do with~sitearg~ f = Settings.withConnectionPool $ \p -> do
flip runConnectionPool p $ runMigration $ do flip runConnectionPool p $ runMigration $ do

View File

@ -1,7 +1,7 @@
The following license covers this documentation, and the source code, except The following license covers this documentation, and the source code, except
where otherwise indicated. where otherwise indicated.
Copyright 2010, ~name~. All rights reserved. Copyright ~year~, ~name~. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:

View File

@ -3,6 +3,9 @@ module Model where
import Yesod import Yesod
-- You can define all of your database entities here. You can find more
-- information on persistent and how to declare entities at:
-- http://docs.yesodweb.com/book/persistent/
mkPersist [$persist| mkPersist [$persist|
User User
ident String ident String
@ -13,5 +16,5 @@ Email
user UserId null update user UserId null update
verkey String null update verkey String null update
UniqueEmail email UniqueEmail email
|~~] |]

View File

@ -3,6 +3,13 @@ module Handler.Root where
import ~sitearg~ import ~sitearg~
-- This is a handler function for the GET request method on the RootR
-- resource pattern. All of your resource patterns are defined in
-- ~sitearg~.hs; look for the line beginning with mkYesodData.
--
-- The majority of the code you will write in Yesod lives in these handler
-- functions. You can spread them across multiple files if you are so
-- inclined, or create a single monolithic file.
getRootR :: Handler RepHtml getRootR :: Handler RepHtml
getRootR = do getRootR = do
mu <- maybeAuth mu <- maybeAuth

View File

@ -1,4 +1,9 @@
{-# LANGUAGE CPP #-} {-# LANGUAGE CPP #-}
-- | Settings are centralized, as much as possible, into this file. This
-- includes database connection settings, static file locations, etc.
-- In addition, you can configure a number of different aspects of Yesod
-- by overriding methods in the Yesod typeclass. That instance is
-- declared in the ~sitearg~.hs file.
module Settings module Settings
( hamletFile ( hamletFile
, cassiusFile , cassiusFile
@ -19,6 +24,76 @@ import Language.Haskell.TH.Syntax
import Database.Persist.~upper~ import Database.Persist.~upper~
import Yesod (MonadCatchIO) import Yesod (MonadCatchIO)
-- | The base URL for your application. This will usually be different for
-- development and production. Yesod automatically constructs URLs for you,
-- so this value must be accurate to create valid links.
approot :: String
#ifdef PRODUCTION
-- You probably want to change this. If your domain name was "yesod.com",
-- you would probably want it to be:
-- > approot = "http://www.yesod.com"
-- Please note that there is no trailing slash.
approot = "http://localhost:3000"
#else
approot = "http://localhost:3000"
#endif
-- | The location of static files on your system. This is a file system
-- path. The default value works properly with your scaffolded site.
staticdir :: FilePath
staticdir = "static"
-- | The base URL for your static files. As you can see by the default
-- value, this can simply be "static" appended to your application root.
-- A powerful optimization can be serving static files from a separate
-- domain name. This allows you to use a web server optimized for static
-- files, more easily set expires and cache values, and avoid possibly
-- costly transference of cookies on static files. For more information,
-- please see:
-- http://code.google.com/speed/page-speed/docs/request.html#ServeFromCookielessDomain
--
-- If you change the resource pattern for StaticR in ~sitearg~.hs, you will
-- have to make a corresponding change here.
--
-- To see how this value is used, see urlRenderOverride in ~sitearg~.hs
staticroot :: String
staticroot = approot ++ "/static"
-- | The database connection string. The meaning of this string is backend-
-- specific.
connStr :: String
#ifdef PRODUCTION
connStr = "~connstr2~"
#else
connStr = "~connstr1~"
#endif
-- | Your application will keep a connection pool and take connections from
-- there as necessary instead of continually creating new connections. This
-- value gives the maximum number of connections to be open at a given time.
-- If your application requests a connection when all connections are in
-- use, that request will fail. Try to choose a number that will work well
-- with the system resources available to you while providing enough
-- connections for your expected load.
--
-- Also, connections are returned to the pool as quickly as possible by
-- Yesod to avoid resource exhaustion. A connection is only considered in
-- use while within a call to runDB.
connectionCount :: Int
connectionCount = 10
-- The rest of this file contains settings which rarely need changing by a
-- user.
-- The following three functions are used for calling HTML, CSS and
-- Javascript templates from your Haskell code. During development,
-- the "Debug" versions of these functions are used so that changes to
-- the templates are immediately reflected in an already running
-- application. When making a production compile, the non-debug version
-- is used for increased performance.
--
-- You can see an example of how to call these functions in Handler/Root.hs
hamletFile :: FilePath -> Q Exp hamletFile :: FilePath -> Q Exp
#ifdef PRODUCTION #ifdef PRODUCTION
hamletFile x = H.hamletFile $ "hamlet/" ++ x ++ ".hamlet" hamletFile x = H.hamletFile $ "hamlet/" ++ x ++ ".hamlet"
@ -40,32 +115,13 @@ juliusFile x = H.juliusFile $ "julius/" ++ x ++ ".julius"
juliusFile x = H.juliusFileDebug $ "julius/" ++ x ++ ".julius" juliusFile x = H.juliusFileDebug $ "julius/" ++ x ++ ".julius"
#endif #endif
connStr :: String -- The next two functions are for allocating a connection pool and running
#ifdef PRODUCTION -- database actions using a pool, respectively. It is used internally
connStr = "~connstr2~" -- by the scaffolded application, and therefore you will rarely need to use
#else -- them yourself.
connStr = "~connstr1~"
#endif
connectionCount :: Int
connectionCount = 10
withConnectionPool :: MonadCatchIO m => (ConnectionPool -> m a) -> m a withConnectionPool :: MonadCatchIO m => (ConnectionPool -> m a) -> m a
withConnectionPool = with~upper~Pool connStr connectionCount withConnectionPool = with~upper~Pool connStr connectionCount
runConnectionPool :: MonadCatchIO m => SqlPersist m a -> ConnectionPool -> m a runConnectionPool :: MonadCatchIO m => SqlPersist m a -> ConnectionPool -> m a
runConnectionPool = runSqlPool runConnectionPool = runSqlPool
approot :: String
#ifdef PRODUCTION
approot = "http://localhost:3000"
#else
approot = "http://localhost:3000"
#endif
staticroot :: String
staticroot = approot ++ "/static"
staticdir :: FilePath
staticdir = "static"

View File

@ -10,7 +10,7 @@ category: Web
stability: Experimental stability: Experimental
cabal-version: >= 1.6 cabal-version: >= 1.6
build-type: Simple build-type: Simple
homepage: http://www.yesodweb.com/~project~ homepage: http://~project~.yesodweb.com/
Flag production Flag production
Description: Build the production executable. Description: Build the production executable.
@ -35,8 +35,9 @@ executable simple-server
executable devel-server executable devel-server
if flag(production) if flag(production)
Buildable: False Buildable: False
else
build-depends: wai-handler-devel >= 0.1.0 && < 0.2
main-is: devel-server.hs main-is: devel-server.hs
build-depends: wai-handler-devel >= 0.1.0 && < 0.2
ghc-options: -Wall -O2 ghc-options: -Wall -O2
executable fastcgi executable fastcgi

View File

@ -9,7 +9,7 @@ main = do
, "You can view your app at http://localhost:3000/" , "You can view your app at http://localhost:3000/"
, "" , ""
] ]
_ <- forkIO () run 3000 "Controller" "with~sitearg~" _ <- forkIO $ run 3000 "Controller" "with~sitearg~"
[ "hamlet" [ "hamlet"
, "cassius" , "cassius"
, "julius" , "julius"
@ -21,3 +21,4 @@ main = do
case x of case x of
'q':_ -> putStrLn "Quitting, goodbye!" 'q':_ -> putStrLn "Quitting, goodbye!"
_ -> go _ -> go

View File

@ -27,13 +27,38 @@ import Model
import Control.Monad (join) import Control.Monad (join)
import Data.Maybe (isJust) import Data.Maybe (isJust)
-- | The site argument for your application. This can be a good place to
-- keep settings and values requiring initialization before your application
-- starts running, such as database connections. Every handler will have
-- access to the data present here.
data ~sitearg~ = ~sitearg~ data ~sitearg~ = ~sitearg~
{ getStatic :: Static { getStatic :: Static -- ^ Settings for static file serving.
, connPool :: Settings.ConnectionPool , connPool :: Settings.ConnectionPool -- ^ Database connection pool.
} }
-- | A useful synonym; most of the handler functions in your application
-- will need to be of this type.
type Handler = GHandler ~sitearg~ ~sitearg~ type Handler = GHandler ~sitearg~ ~sitearg~
-- This is where we define all of the routes in our application. For a full
-- explanation of the syntax, please see:
-- http://docs.yesodweb.com/book/web-routes-quasi/
--
-- This function does three things:
--
-- * Creates the route datatype ~sitearg~Route. Every valid URL in your
-- application can be represented as a value of this type.
-- * Creates the associated type:
-- type instance Route ~sitearg~ = ~sitearg~Route
-- * Creates the value resources~sitearg~ which contains information on the
-- resources declared below. This is used in Controller.hs by the call to
-- mkYesodDispatch
--
-- What this function does *not* do is create a YesodSite instance for
-- ~sitearg~. Creating that instance requires all of the handler functions
-- for our application to be in scope. However, the handler functions
-- usually require access to the ~sitearg~Route datatype. Therefore, we
-- split these actions into two functions and place them in separate files.
mkYesodData "~sitearg~" [$parseRoutes| mkYesodData "~sitearg~" [$parseRoutes|
/static StaticR Static getStatic /static StaticR Static getStatic
/auth AuthR Auth getAuth /auth AuthR Auth getAuth
@ -42,16 +67,22 @@ mkYesodData "~sitearg~" [$parseRoutes|
/robots.txt RobotsR GET /robots.txt RobotsR GET
/ RootR GET / RootR GET
|~~] |]
-- Please see the documentation for the Yesod typeclass. There are a number
-- of settings which can be configured by overriding methods here.
instance Yesod ~sitearg~ where instance Yesod ~sitearg~ where
approot _ = Settings.approot approot _ = Settings.approot
defaultLayout widget = do defaultLayout widget = do
mmsg <- getMessage mmsg <- getMessage
pc <- widgetToPageContent $ do pc <- widgetToPageContent $ do
widget widget
addStyle $(Settings.cassiusFile "default-layout") addStyle $(Settings.cassiusFile "default-layout")
hamletToRepHtml $(Settings.hamletFile "default-layout") hamletToRepHtml $(Settings.hamletFile "default-layout")
-- This is done to provide an optimization for serving static files from
-- a separate domain. Please see the staticroot setting in Settings.hs
urlRenderOverride a (StaticR s) = urlRenderOverride a (StaticR s) =
Just $ uncurry (joinPath a Settings.staticroot) $ format s Just $ uncurry (joinPath a Settings.staticroot) $ format s
where where
@ -59,7 +90,14 @@ instance Yesod ~sitearg~ where
ss :: Site StaticRoute (String -> Maybe (GHandler Static ~sitearg~ ChooseRep)) ss :: Site StaticRoute (String -> Maybe (GHandler Static ~sitearg~ ChooseRep))
ss = getSubSite ss = getSubSite
urlRenderOverride _ _ = Nothing urlRenderOverride _ _ = Nothing
-- The page to be redirected to when authentication is required.
authRoute _ = Just $ AuthR LoginR authRoute _ = Just $ AuthR LoginR
-- This function creates static content files in the static folder
-- and names them based on a hash of their content. This allows
-- expiration dates to be set far in the future without worry of
-- users receiving stale content.
addStaticContent ext' _ content = do addStaticContent ext' _ content = do
let fn = base64md5 content ++ '.' : ext' let fn = base64md5 content ++ '.' : ext'
let statictmp = Settings.staticdir ++ "/tmp/" let statictmp = Settings.staticdir ++ "/tmp/"
@ -67,6 +105,7 @@ instance Yesod ~sitearg~ where
liftIO $ L.writeFile (statictmp ++ fn) content liftIO $ L.writeFile (statictmp ++ fn) content
return $ Just $ Right (StaticR $ StaticRoute ["tmp", fn] [], []) return $ Just $ Right (StaticR $ StaticRoute ["tmp", fn] [], [])
-- How to run database actions.
instance YesodPersist ~sitearg~ where instance YesodPersist ~sitearg~ where
type YesodDB ~sitearg~ = SqlPersist type YesodDB ~sitearg~ = SqlPersist
runDB db = fmap connPool getYesod >>= Settings.runConnectionPool db runDB db = fmap connPool getYesod >>= Settings.runConnectionPool db