Skip to content
kosta edited this page Nov 25, 2012 · 4 revisions

If you haven't upgraded to 0.9.4, please see the previous release announcement.

Scaffolding changes

The scaffolding changes reflect simplifications from the move to conduits, and changes to Persistent.

Persistent related

The configuration API has been improved to use JSON as the configuration data structure and otherwise operate more smoothly.

Persistent has been broken up into Store, Unique, and Query interfaces. The module Database.Persist.Base no longer exists; for an import you likely want Database.Persist or Database.Persist.Store

JSON

In module Yesod.Json jsonList -> array, jsonMap -> object The String argument is now a Text.

StaticFiles

In Settings/StaticFiles.hs, the default imports are now:

import Prelude (IO)
import Yesod.Static
import qualified Yesod.Static as Static
import Settings (staticDir)

Foundation.hs

approot

The approot function is used to generate urls. The typeclass function now has diferent forms

data Approot master =
                      ApprootRelative -- ^ No application root.
                    | ApprootStatic Text
                    | ApprootMaster (master -> Text)
                    | ApprootRequest (master -> W.Request -> Text)

approot now defaults to ApprootRelative in the typeclass, which means you will have relative urls (no hostname). So if relative urls work for you, just delete the approot function from your type-class. The default scaffolding implementation now reads the value from your settings:

approot = ApprootMaster $ appRoot . settings

other

If you have this import:

import Yesod hiding (Form, AppConfig (..))

You will get these warnings:

Foundation.hs:24:22: Module `Yesod' does not export `Form'
Foundation.hs:24:28: Module `Yesod' does not export `AppConfig(..)'

remove the hiding.

You probably need to add

import qualified Database.Persist.Store
import Network.HTTP.Conduit (Manager)

and use it in your foundation data type.

, connPool :: Database.Persist.Store.PersistConfigPool Settings.PersistConfig
, persistConfig :: Settings.PersistConfig
, manager :: Manager

Thanks to conduits, there is no more liftIOHandler! This changes the runDB definition

        runDB f = do
        master <- getYesod
        Database.Persist.Store.runPool
            (persistConfig master)
            f   
            (connPool master)

Add this to your foundation data type

Export this for your routes:

, Route (..)

Application.hs

#if DEVELOPMENT
import Yesod.Logger (Logger, logBS)
import Network.Wai.Middleware.RequestLogger (logHandleDev)
#else
import Yesod.Logger (Logger, logBS, toProduction)
import Network.Wai.Middleware.RequestLogger (logHandle)
#endif
import Network.HTTP.Conduit (newManager, def)

import qualified Database.Persist.Base -> import qualified Database.Persist.Store

Another conduit simiplification: no more inversion of control required in starting your application. So we are changing the naming convention from withFoundationName to just getApplication getApplication now looks like this:

module Application
    ( getApplication
    , getApplicationDev
    ) where

getApplication :: AppConfig DefaultEnv Extra -> Logger -> IO Application
getApplication conf logger = do
    manager <- newManager def
    s <- staticSite
    dbconf <- withYamlEnvironment "config/sqlite.yml" (appEnv conf)
              Database.Persist.Store.loadConfig >>= 
              Database.Persist.Store.applyEnv
    p <- Database.Persist.Store.createPoolConfig (dbconf :: Settings.PersistConfig)
    let foundation = Foo conf setLogger s p manager dbconf
    app <- toWaiAppPlain foundation
    return $ logWare app
#ifdef DEVELOPMENT
    logWare = logHandleDev (logBS setLogger)
    setLogger = logger
#else
    setLogger = toProduction logger -- by default the logger is set for development
    logWare = logHandle (logBS setLogger)
#endif

-- Also add to your .cabal file
-- , http-conduit == 1.2.*

There is a corresponding replacement of withDevelAppPort with the following function:

-- for yesod devel
getApplicationDev :: IO (Int, Application)
getApplicationDev =
    defaultDevelApp loader getApplication
  where
    loader = loadConfig (configSettings Development)
        { csParseExtra = parseExtra
        }

Import.hs

Now exports module Yesod, which is imported with: import Yesod hiding (Route(..))

Settings.hs

In the last release, we added the ability to add arbitrary data to the configuration. We now have some example in the scaffolding. This is an optional, but recommended addition. The extra configuration is read from config/settings.yml

import Prelude
import Control.Applicative
import Data.Yaml

data Extra = Extra
    { extraCopyright :: Text
    , extraAnalytics :: Maybe Text -- ^ Google Analytics
    }   

parseExtra :: DefaultEnv -> Object -> Parser Extra
parseExtra _ o = Extra
    <$> o .:  "copyright"
    <*> o .:? "analytics"

-- in your cabal file
-- , yaml                          >= 0.5        && < 0.6 

-- in Foundation.hs
-- import Settings (widgetFile, Extra(..))
-- settings :: AppConfig DefaultEnv Extra

main.hs

New file contents supporting parsing extra configuration

import Yesod.Default.Config (fromArgs)
import Yesod.Default.Main   (defaultMain)
import Prelude              (IO)
import Settings             (parseExtra)
import Application          (getApplication)

main :: IO ()
main = defaultMain (fromArgs parseExtra) getApplication

devel.hs

"yesod devel" now expects this file: this lets you customize devel startup. You need to put your package name in place of ~project~

curl https://raw.github.com/yesodweb/yesod/master/yesod/scaffold/devel.hs.cg > devel.hs

project.cabal file

If you use GHC 7.4 you have to add EmptyDataDecls to the extensions section of your cabal file.

Haskellers.com upgrade notes

  • Update the cabal file
    • yesod, yesod-core, yesod-static == 0.10.*
    • aeson-native => aeson (old change), same for blaze-textual if necessary
    • http-enumerator => http-conduit == 1.2.*
    • warp, wai-extra == 1.1.*
    • persistent* == 0.7.*
    • yesod-auth == 0.8.*
    • mime-mail-ses == 0.1.*
    • yesod-form, yesod-newsfeed == 0.4.*
    • Add in yesod-auth-fb (for facebook)
  • Rename Haskellers.hs to Foundation.hs
    • Fix up cabal file
    • Update all other modules
  • Network.Wai.Middleware.Debug => Network.Wai.Middleware.RequestLogger, debug => logStdoutDev
  • Database.Persist.Base => Database.Persist.Store
  • Replace share2 with share
  • withPostgresqlPool => createPostgresqlPool
  • to/fromSinglePiece => to/fromPathPiece
  • HaskellersRoute => Route Haskellers
  • Kill liftIOHandler with fire: completely unnecessary (yay conduits!)
  • Remove RedirectTemporary wherever it appears
  • GGHandler sub master monad => GHandler sub master
  • selectList and a few other functions: returns Entity instead of a pair
  • Add a Manager to the foundation, use it as necessary
  • authPlugins: takes an extra parameter now (likely can just use const)
  • Add authHttpManager to YesodAuth instance
  • jsonMap, jsonList, jsonScalar are finally gone. Check out yesod-json for replacements
  • redirectText (and most others) turn into redirect
  • selectField => selectFieldList
  • withHaskellers => getApplication
  • withDevelApp => getApplicationDev
Clone this wiki locally