Just Add Flow

Share this post
Using Elm pipelines with andThen to decode a multi-object type
justaddflow.substack.com

Using Elm pipelines with andThen to decode a multi-object type

Decode the remote api responses into response types that have two parts: RequestStatus and response-specific type.

Harold Campbell
May 9
1
Share this post
Using Elm pipelines with andThen to decode a multi-object type
justaddflow.substack.com

This post shares wow I use pipelines and andThen to Decode a multi-object type.

My payload from the remote service has the following form: 

{

    action: "UpdateCardRequest"
    errorCode: 0
    message: "ok"
    successStatus: true

    jsonBody: {ID: "M949U4J8", TeamID: "J888Y3B1", BoardID: "A954N8A2", StageID: "U345M9U4",…}

}

This response consists of two logically distinct pieces of information, a response status (action, errorCode, message and successStatus) and the context specific payload (jsonBody).

Because of this I want to decode the remote api response into Response types that have two parts RequestStatus and response-specific type.

type LoadingTeamResponse
    = FetchTeamResponse RequestStatus Team


type LoadedTeamResponse
    = CreateBoardStageResponse RequestStatus Stage
    | CreateStageCardResponse RequestStatus Card
    | UpdateStageCardResponse RequestStatus Card


type alias RequestStatus =
    { action : String
    , errorCode : Int
    , successStatus : Bool
    , message : String
    }

My initial approach was to use map4 from the Decoder module, which works but feels clumsy.

postFormResponseDecoder : Decoder ApiResponse
postFormResponseDecoder =
    D.map4 (\a b c d -> PostFormRedirect (RequestStatus a b c) d)
        (D.field "action" D.string)
        (D.field "errorCode" D.int)
        (D.field "successStatus" D.bool)
        (D.maybe (D.field "jsonBody" Team.teamDecoder))

Instead, I used a helper function that allowed for a more concise api.

onApiResponse : Decoder a -> (RequestStatus -> a -> b) -> Decoder b
onApiResponse fieldDecoder responseMessage =
    (D.succeed ApiHTTPResponse
        |> required "action" D.string
        |> required "errorCode" D.int
        |> required "successStatus" D.bool
        |> required "message" D.string
        |> required "jsonBody" fieldDecoder

    )

        |> D.andThen
            (\a ->
                D.succeed (responseMessage (RequestStatus a.action a.errorCode a.successStatus a.message) a.jsonBody)
            )

I can now write my decoders using the onApiResponse. The pattern feels more concise.

fetchTeamResponseDecoder : Decoder LoadingTeamResponse
fetchTeamResponseDecoder =
    onApiResponse teamDecoder FetchTeamResponse
apiGetTeam : String -> Cmd Msg
apiGetTeam teamID =
    Http.get
        { url = getRouteURL "getTeam" ++ teamID
        , expect = Http.expectJson LoadingApiResponse fetchTeamResponseDecoder
        }
Share this post
Using Elm pipelines with andThen to decode a multi-object type
justaddflow.substack.com
Comments

Create your profile

0 subscriptions will be displayed on your profile (edit)

Skip for now

Only paid subscribers can comment on this post

Already a paid subscriber? Sign in

Check your email

For your security, we need to re-authenticate you.

Click the link we sent to , or click here to sign in.

TopNew

No posts

Ready for more?

© 2022 Harold Campbell
Privacy ∙ Terms ∙ Collection notice
Publish on Substack Get the app
Substack is the home for great writing