Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Insert default timestamp in fromJson

I have an ajax call sending json to a route in Yesod and I want the route to parse the json and insert it directly into the database. In my model file I have

createtime UTCTime default=now()

which is preventing parsing the json since the client isn't sending down the createtime. I tried to write my own parseJson for log entries, but I've been unable to insert a UTCTime default since getCurrentTime returns a value in the IO monad. I'd like the database to set the value, if possible.

The only thing I can think of at this point is to make a type like LogEntryWithoutTime, parse the JSON into that and convert to a LogEntry. Is there an easier way?

Edit: I show three different failures to add getCurrentTime to the JSON parse. First, the intent is to parse the createtime if available, and default to getCurrentTime on the server. This isn't right anyways, since we shouldn't rely on the client's time.

instance FromJSON Log where
    parseJSON (Object o) = Log
        <$> o .: "userid"
        ...
        <*> o .:? "createtime" .!= liftIO getCurrentTime

The error is

Model.hs:58:32:
Couldn't match expected type ‘UTCTime’
            with actual type ‘m0 UTCTime’
In the second argument of ‘(.!=)’, namely ‘liftIO getCurrentTime’
In the second argument of ‘(<*>)’, namely
  ‘o .:? "createtime" .!= liftIO getCurrentTime’

Second, I try to just get the current time.

<*> liftIO getCurrentTime

and I get the error

Model.hs:58:9:
No instance for (MonadIO
                   aeson-0.7.0.6:Data.Aeson.Types.Internal.Parser)
  arising from a use of ‘liftIO’
In the second argument of ‘(<*>)’, namely ‘liftIO getCurrentTime’

If I change the line to

<*> getCurrentTime

then I get

Model.hs:58:9:
Couldn't match type ‘IO’
              with ‘aeson-0.7.0.6:Data.Aeson.Types.Internal.Parser’
Expected type: aeson-0.7.0.6:Data.Aeson.Types.Internal.Parser
                 UTCTime
  Actual type: IO UTCTime
like image 936
user3776949 Avatar asked Jul 01 '14 02:07

user3776949


1 Answers

The thing with the default attribute defined in a model is that you still need to define all the values when persisting entities. Defaults are there just for the automatic migrations and schema definitions, as far as I'm aware.

Try lifting the getCurrentTime from the IO monad (with liftIO).

like image 103
ms. Avatar answered Sep 28 '22 00:09

ms.