1

I'm new to Persistent and trying to figure out how to fetch a row using an ID. The docs show an example that looks like this:

personId <- insert $ Person "Michael" "Snoyman" 26
maybePerson <- get personId
case maybePerson of
    Nothing -> liftIO $ putStrLn "Just kidding, not really there"
    Just person -> liftIO $ print person

This example uses the ID generated from insertion to do the query. I don't fully understand how it works, but the idea here is that there are type safe keys so that one cannot query for a Foo with a BarID.

How can I generate a type safe ID/Key for my particular entity? I'd like to be able to take an Int, for example from some url path, and then query my table with that as an ID.

LuxuryMode
  • 33,401
  • 34
  • 117
  • 188
  • Did you take a look at the Persistent page of the Yesod Web Framework Book ? http://www.yesodweb.com/book/persistent – zigazou May 14 '15 at 14:24
  • @zigazou as I linked to in my question, yes. – LuxuryMode May 14 '15 at 14:42
  • I’m also new to Persistent and Yesod. This page helped me to understand how it works. Could you be more precise on what blocks you ? Have you tried the scaffolded site ? – zigazou May 14 '15 at 14:49
  • @Cubic close, but that question is Yesod-specific – LuxuryMode May 14 '15 at 17:21
  • @LuxuryMode It's not. Yesod is in the title, but it's about Persist and the answer has nothing to do with Yesod. – Cubic May 14 '15 at 17:30
  • @Cubic you're right, I didn't look closely enough. toSqlKey is what I was looking for. What should I do with this question now, vote to close? ;) – LuxuryMode May 14 '15 at 17:47

1 Answers1

0

As an example, say I have an Article in my models file :

Article
    artname     Text
    title       Text
    keywords    Text Maybe
    description Text Maybe
    body        Markdown
    parent      ArticleId Maybe
    user        UserId
    lastUpdate  UTCTime
    weight      Int
    public      Bool

    UniqueArt   artname

    deriving    Typeable

I do not need to create a primary key articleId as it is handled by Persistent.

In my routes file:

/new/page                       ArticleNewR GET POST
/page/#ArticleId/edit           ArticleEditR GET POST
/page/#ArticleId/delete         ArticleDeleteR GET POST
/page/#ArticleId                ArticleViewR GET

The #ArticleId tells Yesod to only accept an ArticleId as second argument in my URLs. The Article*R are just handlers for each URL.

In Handler/Article.hs, I need to have the corresponding function handlers. For example, if I told Yesod of the ArticleViewR GET handler, I need to define the following function:

getArticleViewR :: ArticleId -> Handler Html
getArticleViewR articleId = do
    -- The article
    article <- runDB $ get404 articleId

    -- The parent article (if any)
    let parentIdM = articleParent article
    parentM <- case parentIdM of
                    Just parentId -> runDB $ get parentId
                    Nothing -> return Nothing

    -- The child articles
    children <- runDB $ selectList [ArticleParent ==. Just articleId]
                                   [Asc ArticleWeight, Asc ArticleTitle]

    -- Author
    author <- runDB $ get (articleUser article)

    defaultLayout $ do
        setTitle $ toHtml (articleTitle article)
        setDescription $ articleDescription article
        setKeywords $ articleKeywords article
        setAuthor $ userUsername <$> author
        $(widgetFile "article/view")

That’s basically how you link each piece.

zigazou
  • 1,725
  • 9
  • 13
  • This is very helpful, thank you! I am not using Yesod however. I'm using Persistent as a standalone ORM together with Scotty on the web side of things. – LuxuryMode May 14 '15 at 15:23