如果我们在模型文件中定义了2个简单对象,例如: -
Person
name Text
Age Int
Book
title Text
author Text
我们可以为Book定义一个适用表格: -
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形式吗?
谢谢!
答案 0 :(得分:6)
错误消息表示您正在尝试将Text(来自字段结果)用作Key。
您可以使用checkMMap
来包装textField并修改结果:
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)
如果向Person字段添加唯一构造函数,findAuthor
函数会变得更简单:
Person
name Text
...
UniquePerson name
然后代替selectFirst ...
你可以做
mperson <- runDB $ getBy $ UniquePerson name