Haskell Постоянные строки вставки, если их еще нет в базе данных
Я пытаюсь использовать Yesod и настойчивые для создания веб-сайта. Я немного озадачен тем, как использовать постоянный API.
Вот два моих стола
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 }
1 ответ
insertBy не принимает ограничение Unique в качестве параметра, 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