Fix intro/part9
This commit is contained in:
@@ -40,7 +40,7 @@ import Html.Attributes exposing (class)
|
||||
import Html.Events exposing (stopPropagationOn)
|
||||
import Http
|
||||
import HttpBuilder exposing (RequestBuilder, withBody, withExpect, withQueryParams)
|
||||
import Json.Decode as Decode exposing (Decoder, bool, int, list, string)
|
||||
import Json.Decode as Decode exposing (Decoder)
|
||||
import Json.Decode.Pipeline exposing (custom, hardcoded, required)
|
||||
import Json.Encode as Encode
|
||||
import Markdown
|
||||
@@ -83,6 +83,47 @@ type Article a
|
||||
= Article Internals a
|
||||
|
||||
|
||||
{-| Metadata about the article - its title, description, and so on.
|
||||
|
||||
Importantly, this module's public API exposes a way to read this metadata, but
|
||||
not to alter it. This is read-only information!
|
||||
|
||||
If we find ourselves using any particular piece of metadata often,
|
||||
for example `title`, we could expose a convenience function like this:
|
||||
|
||||
Article.title : Article a -> String
|
||||
|
||||
If you like, it's totally reasonable to expose a function like that for every one
|
||||
of these fields!
|
||||
|
||||
(Okay, to be completely honest, exposing one function per field is how I prefer
|
||||
to do it, and that's how I originally wrote this module. However, I'm aware that
|
||||
this code base has become a common reference point for beginners, and I think it
|
||||
is _extremely important_ that slapping some "getters and setters" on a record
|
||||
does not become a habit for anyone who is getting started with Elm. The whole
|
||||
point of making the Article type opaque is to create guarantees through
|
||||
_selectively choosing boundaries_ around it. If you aren't selective about
|
||||
where those boundaries are, and instead expose a "getter and setter" for every
|
||||
field in the record, the result is an API with no more guarantees than if you'd
|
||||
exposed the entire record directly! It is so important to me that beginners not
|
||||
fall into the terrible "getters and setters" trap that I've exposed this
|
||||
Metadata record instead of exposing a single function for each of its fields,
|
||||
as I did originally. This record is not a bad way to do it, by any means,
|
||||
but if this seems at odds with <https://youtu.be/x1FU3e0sT1I> - now you know why!
|
||||
See commit c2640ae3abd60262cdaafe6adee3f41d84cd85c3 for how it looked before.
|
||||
)
|
||||
|
||||
-}
|
||||
type alias Metadata =
|
||||
{ description : String
|
||||
, title : String
|
||||
, tags : List String
|
||||
, createdAt : Time.Posix
|
||||
, favorited : Bool
|
||||
, favoritesCount : Int
|
||||
}
|
||||
|
||||
|
||||
type alias Internals =
|
||||
{ slug : Slug
|
||||
, author : Author
|
||||
@@ -170,39 +211,15 @@ internalsDecoder maybeCred =
|
||||
|> custom metadataDecoder
|
||||
|
||||
|
||||
type alias Metadata =
|
||||
{ description : String
|
||||
, title : String
|
||||
, tags : List String
|
||||
, favorited : Bool
|
||||
, favoritesCount : Int
|
||||
, createdAt : Time.Posix
|
||||
}
|
||||
|
||||
|
||||
metadataDecoder : Decoder Metadata
|
||||
metadataDecoder =
|
||||
{- 👉 TODO: replace the calls to `hardcoded` with calls to `required`
|
||||
in order to decode these fields:
|
||||
|
||||
--- "description" -------> description : String
|
||||
--- "title" -------------> title : String
|
||||
--- "tagList" -----------> tags : List String
|
||||
--- "favorited" ---------> favorited : Bool
|
||||
--- "favoritesCount" ----> favoritesCount : Int
|
||||
|
||||
Once this is done, the articles in the feed should look normal again.
|
||||
|
||||
💡 HINT: Order matters! These must be decoded in the same order
|
||||
as the order of the fields in `type alias Metadata` above. ☝️
|
||||
-}
|
||||
Decode.succeed Metadata
|
||||
|> hardcoded "(needs decoding!)"
|
||||
|> hardcoded "(needs decoding!)"
|
||||
|> hardcoded []
|
||||
|> hardcoded False
|
||||
|> hardcoded 0
|
||||
|> required "description" (Decode.map (Maybe.withDefault "") (Decode.nullable Decode.string))
|
||||
|> required "title" Decode.string
|
||||
|> required "tagList" (Decode.list Decode.string)
|
||||
|> required "createdAt" Timestamp.iso8601Decoder
|
||||
|> required "favorited" Decode.bool
|
||||
|> required "favoritesCount" Decode.int
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user