2013-05-27 18 views
6

如果我們在我們的模型文件中定義了兩個簡單的物體,例如: -如何在Yesod中爲外鍵定義應用表單上的字段?

Person 
    name Text 
    Age Int 
Book 
    title Text 
    author Text 

我們可以定義一個應用形式的圖書爲: -

addBookForm = renderDivs $ Book 
    <$> areq textField "title" Nothing 
    <*> areq textField "author" Nothing 

但是,如果我們想改變筆者從剛剛的文本字段,一個人的ID,如: -

Book 
    title Text 
    author PersonId 

接着上面的表格將不能編譯,與此錯誤: -

Couldn't match expected type `KeyBackend Database.Persist.GenericSql.Raw.SqlBackend Person' with actual type `Text' 
Expected type: Field 
       sub0 
       master0 
       (KeyBackend Database.Persist.GenericSql.Raw.SqlBackend Person) 
    Actual type: Field sub0 master0 Text 
In the first argument of `areq', namely `textField' 
In the second argument of `(<*>)', namely 
    `areq textField "author" Nothing' 

我們現在如何定義作者字段? 我們是否需要使用monadic形式?

謝謝!

回答

6

錯誤消息表示您正嘗試使用Text(來自字段結果)作爲Key。

您可以使用checkMMap包裹的文本框,並修改結果:

addBookForm = renderDivs $ Book 
    <$> areq textField "title" Nothing 
    <*> (entityKey <$> areq authorField "author" Nothing) 
    where 
    authorField = checkMMap findAuthor (personName . entityVal) textField 

    findAuthor name = do 
    mperson <- runDB $ selectFirst [PersonName ==. name] [] 
    case mperson of 
     Just person -> return $ Right person 
     Nothing  -> return $ Left ("Person not found." :: Text) 

findAuthor功能變得更簡單,如果你添加一個獨特的構造函數的人場:

Person 
    name Text 
    ... 
    UniquePerson name 

然後代替selectFirst ...你可以做

mperson <- runDB $ getBy $ UniquePerson name 
相關問題