Let’s create a new directory called post-app
inside beginning-elm
instead of cluttering the src
directory with too many modules.
We need to add post-app
to the source-directories
list in elm.json
.
Creating the Post Module
Let’s move the Post
type and the code for decoding it from DecodingJson.elm
to a new module. Create a new file called Post.elm
inside the post-app
directory and add the code below to it.
Using Custom Types for ID
Currently, the id
field in Post
is an integer. We could mistakenly pass an identifier of a different data structure, which also happens to be an integer, to a function expecting a post id
. The Elm compiler won’t be able to catch a bug like that. We can help the compiler by implementing identifiers as custom types. Add the following code below the Post
type alias in Post.elm
.
PostId
is an opaque type. Let’s expose it in the module definition.
Change the id
field’s type in Post
from Int
to PostId
.
PostId
Decoder
Now that id
is a custom type, simply using the int
decoder in postDecoder
won’t be enough. We need to create a custom decoder. Add the following code to the bottom of Post.elm
.
We used the Decode.map
function to convert an integer to PostId
. Here is what its type signature looks like:
Now we can replace int
with idDecoder
in postDecoder
.
Converting PostId
to String
The viewPost
function in DecodingJson.elm
uses String.fromInt
to convert an id
to a string.
Now that the id
field holds a value of a custom type that’s not going to work. We need to define a custom function for that. Add the following code to the bottom of Post.elm
.
Note: Although we’re moving away from DecodingJson.elm
, we’ll still be using the viewPost
function in a module responsible for fetching and displaying posts in the next section.
idToString
uses pattern matching to expose the underlying integer value inside the PostId
data constructor. Without this ability, we’d be forced to use a case
expression which is not as elegant.
Finally we need to expose idToString
in the module definition.
In the next section, we’ll create a separate page for fetching and listing all posts in our database.