IHP 1.3 is out now!

Help needed with validateFieldIO

axelbdt

Hello everyone, I am looking for a little help with the usage of validateFieldIO, as I am not used to the IO Monad yet.

My user creates a bill for one of his clients by selecting him in a form in the NewBill action. The user is presented with his clients only in the list (obviously) but I want to check he submits a client that belongs to him (in case the post request gets modified). So here is the code:

action CreateBillAction = do
bill <- buildBill (newRecord @Bill)
bill
    |> ifValid \case
    -- proceed with creation

buildBill bill = bill
    |> fill @["userId","clientId"]
    |> validateFieldIO #clientId (validateClientBelongsToUser currentUserId)

validateClientBelongsToUser userId clientId = do
    client <- fetch clientId
    return (if userId == get #userId client then Success else Failure "Not yours")

I get the following type error:

    * Couldn't match type `IO Bill'
                     with `Bill' (Id' "users") (Id' "clients") (QueryBuilder "trips")'
      Expected type: IO Bill -> IO ()
        Actual type: Bill -> IO ()
    * In the second argument of `(|>)', namely
        `ifValid
           \case

I do understand the error message, but I thought that if bill is assigned with the <- in the do block, then it won't be wrapped in IO when I use it in the next lines.

I'd be glad if you could explain this to me and how validateFieldIO is actually used. Thanks in advance :)

montmorency BUSINESS

With IO validation instead of using |> (function application) can you try binding the validation call e.g.:

bill >>= ifValid \case

The arrows have to change from the case of a pure function when there is IO in the validation function.

There's an example of doing IO with validation in the docs.

axelbdt

Thanks a lot for the helpful response, it works now!