Home > database >  Accessing user fields in controller helper does not work
Accessing user fields in controller helper does not work

Time:10-14

Context

In a controller, I have a function that is called via beforeAction to check if a certain field on user is null or not. If it is null, the user should be redirected to a certain action in another controller.

Since I want to call this function from almost every controller in my application, putting it in Application.Helper.Controller seems the right choice, but I cannot figure out the type signature.

The function is as follows, and in a normal controller this works:

ensureIsSubscribed :: _ => IO ()
ensureIsSubscribed = do
    case currentUserOrNothing of
        Just loggedInUser -> do
            case (get #subscriptionId loggedInUser) of
                Nothing -> redirectToPath "/NewCheckoutSession"
                _ -> redirectToPath "/Welcome"
        Nothing -> pure ()

but when putting the above in Application.Helper.Controller I get this error:

Could not deduce (HasField
                      "subscriptionId" CurrentUserRecord (Maybe a0))
    arising from a use of ‘get’
  from the context: ?context::ControllerContext
    bound by the inferred type of
               ensureIsSubscribed :: (?context::ControllerContext) => IO ()
    at Application/Helper/Controller.hs:(8,1)-(14,26)
  The type variable ‘a0’ is ambiguousIn the expression: (get #subscriptionId loggedInUser)
  In a stmt of a 'do' block:
    case (get #subscriptionId loggedInUser) of
      Nothing -> redirectToPath "/NewCheckoutSession"
      _ -> redirectToPath "/Welcome"
  In the expression:
    do case (get #subscriptionId loggedInUser) of
         Nothing -> redirectToPath "/NewCheckoutSession"
         _ -> redirectToPath "/Welcome"
   |
11 |             case (get #subscriptionId loggedInUser) of
   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Question

Why does the above not work and what is the correct type signature (if that is the problem)?

CodePudding user response:

The CurrentUserRecord is defined in Web/Types.hs as type instance CurrentUserRecord = User. If the Web.Types module is not imported, the type CurrentUserRecord cannot be replaced with it's definition User.

The fix is therefore to add an import Web.Types to your Application.Helper.Controller module :)

  • Related