2013-04-30 68 views
6

我正在嘗試使用Yesod和持久性來創建網站。我對如何使用持久性API有點困惑。Haskell持久插入行(如果尚未在數據庫中)

這裏是我的兩個表的

Feed 
    url Text 
    UniqueFeed url 

Subscription 
    feed FeedId 
    title Text 
    UniqueSubscription feed 

我試圖創建一個頻道如果與URL飼料不存在,然後訂閱添加到飼料,如果訂閱不存在。

postFeedR :: Handler RepHtml 
postFeedR = do 
    url <- runInputPost $ ireq urlField "url" 
    title <- runInputPost $ ireq textField "title" 

    runDB $ do 
     feedId <- insertFeed $ UniqueFeed url 
     subscriptionId <- insertSubscription feedId title 
     return 

    defaultLayout [whamlet| <p>done|] 

insertFeed url = do 
    f <- insertBy $ UniqueFeed url 
    case f of 
     Left (Entity uid _) -> uid 
     Right (Key uid) -> do 
      (Key uid) <- insert $ Feed url 
      return uid 

insertSubscription feedId title = do 
    s <- insertBy $ UniqueSubscription feedId 
    case s of 
     Left (Entity uid _) -> uid 
     Right (Key uid) -> do 
      (Key uid) <- insert $ Subscription feedId title 
      return uid 

我在下面的錯誤。我不明白爲什麼ghc認爲insertFeed和insertSubscription的返回值應該是UniqueFeed和UniqueSubscription。我希望這些函數返回新創建記錄的鍵。

此外,它似乎就像我扔掉了我在案件右邊條款中找回的鑰匙。爲什麼持久性返回這些鍵。在UniqueSubscription不在數據庫中的情況下,持久性沒有足夠的信息來創建新的訂閱記錄,因爲它缺少不在UniqueSubscription中的標題。

如果有人可以給我一些關於如何使用持久API的指針,我會非常感激。

Handler/Home.hs:62:9: 
    Kind incompatibility when matching types: 
     a0 :: * 
     GHandler App App :: * -> * 
    Expected type: (a0 -> t0) 
        -> (t0 -> a0 -> m0 a0) -> YesodDB App App (m0 a0) 
     Actual type: (a0 -> t0) -> (t0 -> a0 -> m0 a0) -> a0 -> m0 a0 
    In a stmt of a 'do' block: feedId <- insertFeed $ UniqueFeed url 
    In the second argument of `($)', namely 
     `do { feedId <- insertFeed $ UniqueFeed url; 
      subscriptionId <- insertSubscription feedId title; 
      return }' 

Handler/Home.hs:62:9: 
    Couldn't match type `YesodPersistBackend App' with `(->)' 
    Expected type: (a0 -> t0) 
        -> (t0 -> a0 -> m0 a0) -> YesodDB App App (m0 a0) 
     Actual type: (a0 -> t0) -> (t0 -> a0 -> m0 a0) -> a0 -> m0 a0 
    In a stmt of a 'do' block: feedId <- insertFeed $ UniqueFeed url 
    In the second argument of `($)', namely 
     `do { feedId <- insertFeed $ UniqueFeed url; 
      subscriptionId <- insertSubscription feedId title; 
      return }' 

Handler/Home.hs:74:20: 
    Couldn't match expected type `Unique Feed' 
       with actual type `Database.Persist.Store.PersistValue' 
    In the first argument of `return', namely `uid' 
    In a stmt of a 'do' block: return uid 
    In the expression: 
     do { (Key uid) <- insert $ Feed url; 
      return uid } 

Handler/Home.hs:83:20: 
    Couldn't match expected type `Unique Subscription' 
       with actual type `Database.Persist.Store.PersistValue' 
    In the first argument of `return', namely `uid' 
    In a stmt of a 'do' block: return uid 
    In the expression: 
     do { (Key uid) <- insert $ Subscription feedId title; 
      return uid } 
+0

嘗試使用'insertBy $ Feed url'。 – 2013-04-30 10:53:19

回答

7

insertBy不採取獨特的約束作爲參數,getBy是比較合適的。

insertUnique 是Maybe結果的可能性很小。

postFeedR :: Handler RepHtml 
postFeedR = do 
    url <- runInputPost $ ireq urlField "url" 
    title <- runInputPost $ ireq textField "title" 

    runDB $ do 
     feedId <- insertFeed url 
     _mbSubscriptionId <- insertUnique $ Subscription feedId title 
     return() 

    defaultLayout ... 

insertFeed url = do 
    f <- insertBy $ Feed url 
    case f of 
     Left (Entity uid _) -> return uid 
     Right uid -> return uid