2014-07-01 5 views
7

Ich habe einen Ajax Anruf senden Json zu einer Route in Yesod und ich möchte die Route zu analysieren, die JSON und fügen Sie es direkt in die Datenbank. In meinem Modell-Datei habe ichStandard-Zeitstempel in fromJson einfügen

createtime UTCTime default=now() 

die die json verhindert wird Parsen da der Client die create Senden unten nicht. Ich habe versucht, meinen eigenen parseJson für Protokolleinträge zu schreiben, aber ich konnte keinen UTCTime-Standard einfügen, da getCurrentTime einen Wert in der IO-Monade zurückgibt. Ich möchte, dass die Datenbank den Wert nach Möglichkeit festlegt.

Die einzige Sache, an die ich an diesem Punkt denken kann, ist, einen Typ wie LogEntryWithoutTime zu machen, den JSON darin zu analysieren und in einen LogEntry zu konvertieren. Gibt es einen leichteren Weg?

Bearbeiten: Ich zeige drei verschiedene Fehler, getCurrentTime zum JSON-Parse hinzuzufügen. Zuerst besteht die Absicht darin, die createtime zu analysieren, falls verfügbar, und standardmäßig getCurrentTime auf dem Server zu verwenden. Das ist sowieso nicht richtig, da wir uns nicht auf die Zeit des Kunden verlassen sollten.

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

Der Fehler ist

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’ 

Zweitens versuche ich die aktuelle Zeit nur zu bekommen.

<*> liftIO getCurrentTime 

und erhalte ich die Fehler

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’ 

Wenn ich die Linie zu

<*> getCurrentTime 

dann bekomme ich

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 
+0

Haben Sie dieses Problem herausgefunden? Ich kämpfe jetzt damit. –

+0

Entschuldigung, ich konnte keine gute Lösung finden. – user3776949

Antwort

1

Die Sache mit dem in definierten default Attribut ändern Ein Modell ist t Bei allen persistenten Entitäten müssen Sie noch alle Werte definieren. Standardwerte sind nur für die automatischen Migrationen und Schemadefinitionen vorhanden, soweit mir bekannt ist.

Versuchen Sie, die getCurrentTime von der IO-Monade (mit liftIO) zu heben.

+0

Ich sehe, dass die Modelldatei den Haskell-Code nicht beeinflusst, also habe ich am Ende Raw-SQL geschrieben, um die Zeile einzufügen. Ich habe versucht, liftIO zu benutzen, als ich diese Frage gepostet habe und es hat nicht funktioniert, aber ich erinnere mich nicht an den genauen Fehler. Ich denke, es hat versucht, es in eine andere Monade zu bringen, aber es gab keine andere Monade. – user3776949

+0

Keine Instanz für (MonadIO aeson-0.8.0.2: Data.Aeson.Types.Internal.Parser) –

0

Ich bin jetzt im Wesentlichen das gleiche Problem konfrontiert. Mein gegenwärtiger Gedanke ist, dass, da ich nicht erwarte, dass der Benutzer mir eine vollständige Aufzeichnung zur Verfügung stellt, ich es nicht so modellieren sollte. Stattdessen sollte ich den Anfragekörper modellieren, den ich von dem Benutzer erwarte, und diesen für den Speicher selbst umwandeln.

So können Sie das Konzept eines PartialLog haben, die nur die Felder, die Sie dem Benutzer senden erwarten hat:

data PartialLog = PartialLog { partialLogMessage :: Text } 

Dazu könnte eine Funktion haben, die in die Lücken füllt und bietet Ihnen ein kompletter Satz:

{-# LANGUAGE RecordWildCards #-} 

logFromPartial :: PartialLog -> UserId -> IO Log 
logFromPartial p u = do 
    let logUserId = u 
     logMessage = partialLogMessage p 
    logCreatetime <- liftIO getCurrentTime 
    return Log{..} 

nb Ich übergebe die UserId, weil wir wollen, dass dieser Wert von der authentifizierten Sitzung kommt; Es ist nicht notwendig, dass der Benutzer uns seine ID mitteilt.