今天早上我跟着这个有趣的教程学习如何使用 Servant 构建一个简单的 API 服务器。
在教程的最后,作者建议添加一个博客类型,所以我想我会试一试,但是我在尝试实现和序列化扩展教程中逻辑的外键关系时遇到了困难(也许是一个重要的此处披露:我对仆人和持久性都是新手)。
这是我的持久定义(我添加了Post
):
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
User
name String
email String
deriving Show
Post
title String
user UserId
summary String
content String
deriving Show
|]
本教程为 Servant API 构建了一个单独的Person
数据类型,所以我也添加了一个名为Article
:
-- API Data Types
data Person = Person
{ name :: String
, email :: String
} deriving (Eq, Show, Generic)
data Article = Article
{ title :: String
, author :: Person
, summary :: String
, content :: String
} deriving (Eq, Show, Generic)
instance ToJSON Person
instance FromJSON Person
instance ToJSON Article
instance FromJSON Article
userToPerson :: User -> Person
userToPerson User{..} = Person { name = userName, email = userEmail }
但是,现在,当我尝试创建一个将 aPost
转换为的函数时Article
,我在尝试处理User
外键时遇到了困难:
postToArticle :: Post -> Article
postToArticle Post{..} = Article {
title = postTitle
, author = userToPerson postUser -- this fails
, summary = postSummary
, content = postContent
}
我尝试了很多东西,但上面的内容似乎接近我想要进入的方向。但是,由于以下错误,它无法编译:
Couldn't match expected type ‘User’
with actual type ‘persistent-2.2.2:Database.Persist.Class.PersistEntity.Key
User’
In the first argument of ‘userToPerson’, namely ‘postUser’
In the ‘author’ field of a record
最终,我不太确定 a 到底是什么PersistEntity.Key User
,我错误的谷歌搜索并没有让我更接近。
我该如何处理这种外键关系?
工作版本
postToArticle :: MonadIO m => Post -> SqlPersistT m (Maybe Article)
postToArticle Post{..} = do
authorMaybe <- selectFirst [UserId ==. postUser] []
return $ case authorMaybe of
Just (Entity _ author) ->
Just Article {
title = postTitle
, author = userToPerson author
, summary = postSummary
, content = postContent
}
Nothing ->
Nothing