Open felipexpert opened 8 years ago
I just tried this and it looks like you would need to add at least these extra dependencies to stack.yaml and then run "stack build".
extra-deps:
Let me know if you need more info. Best, Grant
How can I implement YesodPersist in Yesod?
I tryed the following which doesn't compile:
-- How to run database actions.
instance YesodPersist App where
runDB = runResourceT . runNoLoggingT . withODBCConn Nothing "dsn=mysql_test" . runSqlConn
For instance, I've found the following code from the Yesod book:
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
import Control.Monad.Logger (runNoLoggingT)
import Data.Text (Text)
import Data.Time
import Database.Persist.Sqlite
import Yesod
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Link
title Text
url Text
added UTCTime
|]
data App = App ConnectionPool
mkYesod "App" [parseRoutes|
/ HomeR GET
/add-link AddLinkR POST
|]
instance Yesod App
instance RenderMessage App FormMessage where
renderMessage _ _ = defaultFormMessage
instance YesodPersist App where
type YesodPersistBackend App = SqlBackend
runDB db = do
App pool <- getYesod
runSqlPool db pool
getHomeR :: Handler Html
getHomeR = defaultLayout
[whamlet|
<form method=post action=@{AddLinkR}>
<p>
Add a new link to
<input type=url name=url value=http://>
titled
<input type=text name=title>
<input type=submit value="Add link">
<h2>Existing links
^{existingLinks}
|]
existingLinks :: Widget
existingLinks = do
links <- handlerToWidget $ runDB $ selectList [] [LimitTo 5, Desc LinkAdded]
[whamlet|
<ul>
$forall Entity _ link <- links
<li>
<a href=#{linkUrl link}>#{linkTitle link}
|]
postAddLinkR :: Handler ()
postAddLinkR = do
url <- runInputPost $ ireq urlField "url"
title <- runInputPost $ ireq textField "title"
now <- liftIO getCurrentTime
runDB $ insert $ Link title url now
setMessage "Link added"
redirect HomeR
main :: IO ()
main = runNoLoggingT $ withSqlitePool "links.db3" 10 $ \pool -> liftIO $ do
runSqlPersistMPool (runMigration migrateAll) pool
warp 3000 $ App pool
stack new abcd yesod-simple [ie create project with yesod-simple template just to setup all yesod dependencies]
then add these dependencies to the abcd.cabal file , persistent-odbc , esqueleto
add these extra dependencies to stack.yaml extra-deps:
run: stack build
Create this file: I dont have MySql on my machine so I used sqlite3 instead but it is similar:
the key line is:
pool <- runStderrLoggingT $ createODBCPool (Just (Sqlite True)) "dsn=sqlitetest" 1
Just replace with MySql and you should be running fine
A minor thing, : but I noticed that you had: let conf = OdbcConf "DNS=mysql_test;" 1 "MySQL" [should be DSN=]
{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE ViewPatterns #-} import Control.Monad.Logger import Data.Text (Text) import qualified Database.Esqueleto as E import Database.Esqueleto ((^.)) import Yesod import qualified Data.Conduit.List as CL import Data.Conduit (($=)) import Prelude import Database.Persist.ODBC import Database.Persist.ODBCTypes import Database.Persist.MigrateSqlite import System.IO.Unsafe
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase| Author name Text Blog author AuthorId title Text content Html |]
data App = App { persistConfig :: OdbcConf , connPool :: ConnectionPool } instance Yesod App
instance YesodPersist App where type YesodPersistBackend App = SqlBackend runDB = defaultRunDB persistConfig connPool
instance YesodPersistRunner App where getDBRunner = defaultGetDBRunner connPool
mkYesod "App" [parseRoutes| / HomeR GET /blog/#BlogId BlogR GET |]
getHomeR :: Handler TypedContent
getHomeR = do
let blogsSrc =
E.selectSource
$ E.from $ (blog E.InnerJoin
author) -> do
E.on $ blog ^. BlogAuthor E.==. author ^. AuthorId
return
( blog ^. BlogId
, blog ^. BlogTitle
, author ^. AuthorName
)
render <- getUrlRenderParams
respondSourceDB typeHtml $ do
sendChunkText "
It is working! There is just a issue, when I run the first time with the migrations, a error appears, but then (after commenting it) it works apparently properly: (the error is in the last line)
Run from outside a project, using implicit global project config Using resolver: lts-4.1 from implicit global project's config file: /home/geppetto/.stack/global-project/stack.yaml
getColumns cs=[Right (Left (Column {cName = DBName {unDBName = "name"}, cNull = False, cSqlType = SqlString, cDefault = Nothing, cDefaultConstraintName = Nothing, cMaxLen = Nothing, cReference = Nothing}))]
us=[]
old=[Right (Left (Column {cName = DBName {unDBName = "name"}, cNull = False, cSqlType = SqlString, cDefault = Nothing, cDefaultConstraintName = Nothing, cMaxLen = Nothing, cReference = Nothing}))]
fdefs=[]
getColumns cs=[Right (Left (Column {cName = DBName {unDBName = "author"}, cNull = False, cSqlType = SqlInt64, cDefault = Nothing, cDefaultConstraintName = Nothing, cMaxLen = Nothing, cReference = Nothing})),Right (Left (Column {cName = DBName {unDBName = "title"}, cNull = False, cSqlType = SqlString, cDefault = Nothing, cDefaultConstraintName = Nothing, cMaxLen = Nothing, cReference = Nothing})),Right (Left (Column {cName = DBName {unDBName = "content"}, cNull = False, cSqlType = SqlString, cDefault = Nothing, cDefaultConstraintName = Nothing, cMaxLen = Nothing, cReference = Nothing}))]
us=[]
old=[Right (Left (Column {cName = DBName {unDBName = "author"}, cNull = False, cSqlType = SqlInt64, cDefault = Nothing, cDefaultConstraintName = Nothing, cMaxLen = Nothing, cReference = Nothing})),Right (Left (Column {cName = DBName {unDBName = "title"}, cNull = False, cSqlType = SqlString, cDefault = Nothing, cDefaultConstraintName = Nothing, cMaxLen = Nothing, cReference = Nothing})),Right (Left (Column {cName = DBName {unDBName = "content"}, cNull = False, cSqlType = SqlString, cDefault = Nothing, cDefaultConstraintName = Nothing, cMaxLen = Nothing, cReference = Nothing}))]
fdefs=[]
Migrating: ALTER TABLE blog
ADD CONSTRAINT blog_author_fkey
FOREIGN KEY(author
) REFERENCES author
(id
)
[Debug#SQL] ALTER TABLE blog
ADD CONSTRAINT blog_author_fkey
FOREIGN KEY(author
) REFERENCES author
(id
); []
File.hs: Prelude.chr: bad argument: 5832776
Unfortunately I don't have mysql and am unable to debug this. Best, Grant
Hello gbway, I am following another path. I am trying to integrate persistent-odbc with scotty, looking at this tutorial: http://adit.io/posts/2013-04-15-making-a-website-with-haskell.html
tutorial version using Postgrees:
import Database.Persist
import Database.Persist.Sqlite
runDb :: SqlPersist (ResourceT IO) a -> IO a
runDb query = runResourceT . withSqliteConn "dev.sqlite3" . runSqlConn $ query
but I am getting trouble in the following code:
import Prelude
import Database.Persist
import Database.Persist.ODBC
import Control.Monad.Logger (runNoLoggingT)
import Control.Monad.Trans.Resource (runResourceT, ResourceT)
runDb :: SqlPersist (ResourceT IO) a -> IO a
runDb = runResourceT . runNoLoggingT . (withODBCConn Nothing "dsn=newmyerp") . runSqlConn
But the signature doesn't match...
How can I easily use it with yesod through stack? (By the way, thank you so much for this repo, it was the only way I've found to use Persistent+Mysql+Windows)