In the previous post we’ve managed to create a page with links which are typechecked. I believe that’s really cool, but we’ve missed one ultra-important feature: error 404: Not Found. Current implementation (available with step-by-step changes all the time at GitHub) returns a default page in this case – with <<Unknown>>
project. That’s an ugly workaroud for the fact that we didn’t know how to return errors back then. Now we’re going to learn how to do it.
Let’s start with splitting getProjectR
(in Project.hs
) into three separate functions, like that:
getProjectR :: Int -> Handler Html getProjectR projectId = defaultLayout $ selectPage projectId selectPage :: Int -> Widget selectPage projectId = renderPage project where project = maybe (-1, ""::Text) id projectEntry projectEntry = find (\x -> (fst x) == projectId) projects renderPage :: (Int, Text) -> Widget renderPage projectEntry = do setTitle $ ("Project " ++ projectName) $(widgetFile "project") where projectTitle = (toHtml projectId) ++ (toHtml projectName) projectName = snd projectEntry projectId = fst projectEntry
I’ve added type signatures to top-level functions, both to make GHC stop complaining and to introduce another important topic which we’ll discuss later in the series – Widgets. For now let’s simply assume that Widget
is part of a web page.
Now, since selectPage
is the only entity aware that something might go wrong, we should change it to return a 404 page in such case. It actually turns out to even remove some code:
selectPage :: Int -> Widget selectPage projectId = maybe notFound renderPage projectEntry where projectEntry = find (\x -> (fst x) == projectId) projects
Check it out – it really does the job!
When I started writing this post I thought about implementing it the brute force way (fromJust
). However, classy-prelude
, a modified version of standard library which Yesod relies on doesn’t have a fromJust
function. That turned out being actually quite nice, as I believe current implementation to be quite elegant, while the brute-force one would by, by definition, a brute-force one.
Next episode – more about Widgets – coming still this week. By the way, sorry about the delay in adding this post, I wanted to add it during the weekend but was unable to. I’ll do my best to avoid such situations in the future.
code
more code
~~~~