Hello folks. I will tell here a fake SSCCE to talk about the right approach for a very common use case that I am stuck.
Let’s say I have an API with 3 database entities: User, Job, Location.
You want to be able to create and edit an user, that have only the information of the id of job, you can chose the job in a select field.
Let’s create some code:
module Data.Location exposing (Location, decoder)
type alias Location =
{ id : Int
, name : String
, ...
}
decoder : JD.Decoder Location
decoder =
JD.map2 Location
(JD.field "id" JD.int)
(JD.field "name" JD.string)
------------------------------------
module Data.Job exposing (Job, decoder)
type alias Job =
{ id : Int
, name : String
, location : Location
, ...
}
decoder : JD.Decoder Job
decoder =
JD.map3 Job
(JD.field "id" JD.int)
(JD.field "name" JD.string)
(JD.field "location" Data.Location.decoder) -- Problem [2] and [3]
------------------------------------
module Data.User exposing (User, decoder, encoder)
type alias User =
{ id : Int
, job : Job
, ...
}
decoder : JD.Decoder User
decoder =
JD.map2 User
(JD.field "id" JD.int)
(JD.field "job" Data.Job.decoder)
encoder : User -> JE.Value
encoder user =
JE.object
[ ( "id", JE.int user.id ) -- Problem [1]
, ( "job", JE.int user.job.id)
]
So, this approach have some problems:
[1] This encoder will work for both creating and editing. But when creating it will send id as 0. Works but not great.
[2] Probably in this case Job will receive the json { id, name, id_location }, so Data.Job.decoder can’t reuse the Data.Location.decoder. Is there a way to defining only one decoder for the entity that cover both cases? When pointing to entity or when pointing to the id of entity?
[3] When creating/editing a job, we probably will edit only the ID of the new location. We could chose in a select field. But it would be strange to edit the entity’s id. In this case it would be better if the User entity had id_job, but then I would need to duplicate the Job entity and it’s not ideal.
So I am trying to think in the best nested encode/decode approach that is consistent and is not required to create 2 entities and 2 decoders and 2 encoders for the same thing.
What do you think about it?