6

如果我们在模型文件中定义了 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'

我们现在如何定义作者字段?我们需要使用一元形式吗?

谢谢 !

4

1 回答 1

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)

findAuthor如果向 Person 字段添加一个唯一的构造函数,该函数会变得更简单:

Person
  name Text
  ...
  UniquePerson name

然后selectFirst ...你可以做

mperson <- runDB $ getBy $ UniquePerson name
于 2013-05-28T14:09:26.547 回答