How to define a field in the applicative form for a foreign key in Yesod?

If we defined 2 simple objects in our model file, for example: -

Person name Text Age Int Book title Text author Text 

We can define the applicative form for a book as: -

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

However, if we want to change the author only from the text field, to the person’s identifier, as: -

 Book title Text author PersonId 

Then the above form will not be compiled with this error: -

 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' 

How do we now define the author’s field? Do I need to use a monadic form?

Thanks!

+6
source share
1 answer

The error message means that you are trying to use text (from the result of a field) as a key.

You can use checkMMap to wrap textField and change the result:

 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) 

The findAuthor function becomes easier if you add a unique constructor to the Person field:

 Person name Text ... UniquePerson name 

Then instead of selectFirst ... you can do

 mperson <- runDB $ getBy $ UniquePerson name 
+6
source

Source: https://habr.com/ru/post/945931/


All Articles