4

I'm attempting to fork a non-web service in my Yesod application, and it needs to do some interaction with database. From this post I decided to put the service in makeApplication. I would like my service to return some value when certain things happen and store it into database. Thus, I'm wondering whats the best way to do this?

How do I run runDB $ insert $ Stuff (T.pack "stuff") inside the makeApplication function?

EDIT: As suggested by Michael I made the following helper function inside Application.hs

runDBIO conf foundation f = do
    dbconf <- withYamlEnvironment "config/postgresql.yml" (appEnv conf)
        Database.Persist.loadConfig >>=
        Database.Persist.applyEnv
    p <- Database.Persist.createPoolConfig (dbconf :: Settings.PersistConf)
    logger <- mkLogger True stdout

    runLoggingT
        (Database.Persist.runPool dbconf f p)
        (messageLoggerSource foundation logger)

And in the makeApplication I used it like so:

runDBIO conf foundation $ do
    dbid <- insert $ Stuff (T.pack "some random stuff")
    string <- get dbid
    liftIO $ print string

However, I'm getting this compile error:

No instance for (resourcet-0.4.5:Control.Monad.Trans.Resource.MonadResource IO)
arising from a use of 'insert'

Am I inputting the wrong type for runPool? Or I need to make an instance for insert? I don't see why runMigration migrateAll works but insert does not.

Community
  • 1
  • 1
HHC
  • 2,513
  • 2
  • 18
  • 26

1 Answers1

2

You can see a demonstration of how to run a database action in the IO monad in the scaffolding itself. Essentially you need to provide two pieces of information: how to log queries, and the database connection pool. You could factor that code out into a helper function (e.g., runDBIO), and then run runDBIO $ insert $ Stuff $ T.pack "stuff".

Michael Snoyman
  • 31,100
  • 3
  • 48
  • 77
  • That sounds cool, I'll give it a try! Question, what's your standing on helper functions? I've always thought it was an anti pattern. – HHC May 14 '13 at 01:51
  • Perhaps our definitions of helper functions are different. I just meant a function that factors out some common code, which I definitely wouldn't consider an anti pattern. – Michael Snoyman May 14 '13 at 05:46
  • Yes it makes perfect sense to create a function if it's common code. Maybe what I mean about helper function is like in Java, people make utility classes, putting lots of unrelated functions into the same class. – HHC May 14 '13 at 06:04
  • Putting runResourceT in front of runDBIO solved the problem thanks, referencing this [post](http://stackoverflow.com/questions/15047095/haskell-persistent-sqlite-no-instance-for-control-monad-trans-resource-mona). – HHC May 17 '13 at 05:31