2014-11-02

Posted on November 2, 2014

I’ve now completed the RESTful API for the Todo tutorial. The only really tricky part was writing the Aeson parser (FromJSON instance) for the “wrapped” JSON that Ember hands us. For example:

{"todo":{"title":"Profit!","isCompleted":false}}

My eventual solution looks simple enough, although it took me longer to get there than it should have done:

-- This instance works for both a simple object:
--   {"title":"The Title","isCompleted":"false"}
-- and a wrapped one:
--   {"todo":{"title":"...",...}}
instance FromJSON Todo where
  parseJSON (Object v) = 
    let simple x = Todo <$> x .: "title" <*> x .: "isCompleted"
        wrapped x = x .: "todo" >>= simple
    in simple v <|> wrapped v
  parseJSON _ = mzero

I’m still a bit puzzled as to why the monadic bind operator is the right thing to join x .: "todo" with simple in the definition of wrapped, especially since everything else is applicative. Anyway, it works, and yesod made it incredibly easy to build the rest of the REST. My Todo page now has proper server side, database-backed storage.

I note that Michael Snoyman recently published some notes on GHCJS. Interesting though it might be to be using Haskell on the browser too, I’ve been very impressed so far with Ember; it integrates with Yesod well enough, and it’s no trouble to set up. So that’s the way I’m going.

In terms of flare, I’m going to start the shift towards Ember with the users / domains / addresses pages. First, because they are currently klunky, both in terms of the web interface and the code backing it. And secondly because I want more experience with Ember before I tackle the really important things (messages and folders / tags).

Ah, good! maybeAuthId works as expected for AJAX requests - I don’t need to invent some new authentication mechanism.

So, hmm. How do I add a second unrelated page to my current Ember app? Am I even asking the right question here? I could, of course, have a whole bunch of more or less separate Ember thingies, with Yesod picking the right application.js. But I think Ember wants to handle the routing itself. Time to do some more reading.

OK. So let’s start by hanging some stuff off /conf/. Eventually, I’ll have all the customer, users, domains, and addresses pages here. Looks like it should be relatively simple to bubble up one level and Emberize the whole app if that’s where I want to go…