How can I show a <select> for a has many relationship in Yesod?

134 Views Asked by At

I have a simple one-to-many relationship, say something like this

Process
    name Text

Report
    time Text
    process ProcessId

I'd like to create a form for creating posts where I'll be able to select from a list of existing users. Something like this.

processOptions :: Handler (OptionList (KeyBackend SqlBackend Process))
processOptions = optionsPersist [] [Desc ProcessName] id

postForm = renderDivs $ Report
             <$> areq textField "Time" Nothing
             <*> areq (selectField processOptions) "Process" Nothing

The prolem is, that I can't just figure out how to properly use selectField together with optionsPersist. I've looked at the source code for clues, but I just can't figure out what to do with this.

The expected type of the optionsPersist seems to be Handler (OptionList (KeyBackend SqlBackend Process)), though what it actually returns is Handler (OptionList (Entity Process)). I'm not sure if I'm missing something, or if there's some unwrapping that needs to be done.

Here's the actual error message

Couldn't match type ‘Entity (ProcessGeneric SqlBackend)’
              with ‘KeyBackend SqlBackend Process’
Expected type: Handler (OptionList (KeyBackend SqlBackend Process))
  Actual type: HandlerT
                 App IO (OptionList (Entity (ProcessGeneric SqlBackend)))

While there is a question for a similar topic, I don't think this is a duplicate, as this question is about using optionsPersist, while the other question simply generates the options manually.

1

There are 1 best solutions below

0
On

I think you're almost there. The problem doesn't seem to be in how you're calling selectField or processOptions. The issue is that the result of that call is going to be an Entity Process, whereas the second field in Report is an ProcessId. So you just need to use fmap (aka <$>) to convert. I believe the following will do it:

entityKey <$> (areq (selectField processOptions) "Process" Nothing)