2015-04-16 7 views
14

Wer weiß von einem sauberen Weg, um die ActiveJob::SerializationError zu vermeiden, die beim Versuch auftritt, ein Date oder Time Objekt zu serialisieren?SerializationError Rails ActiveJob Uhrzeit und Datum

Die beiden Lösungen, die ich bisher gehabt haben sind:

  • Anruf Marshal/JSON/YAML dump wenn die Argumente zu laden und dann load zurück in den Job (die saugt, weil ich Affe muss der Patch Mailer Job)
  • Affe Patch Date und Time wie so:

/lib/core_ext/time.rb

/lib/core_ext/date.rb

class Date 

    include GlobalID::Identification 

    def id 
    self.to_time.id 
    end 

    def self.find(id) 
    Time.find(id).to_date 
    end 
end 

Welche auch saugt. Hat jemand eine bessere Lösung?

+2

Ist es wirklich notwendig, nur ein Datum oder eine Uhrzeit an den Job zu übergeben (und warum)? Ich denke, es wäre besser, ein ActiveModel als Parameter an den Job zu übergeben, der möglicherweise eine Datums- oder Zeitinstanz enthält. (ActiveModels enthalten GlobalID :: Identification, damit sie serialisierbar sind) – sourcx

+0

Nein, das ist nicht wirklich notwendig. Es ist einfach praktisch. Darüber hinaus hat es mit DelayedJob funktioniert, bevor wir ActiveJob integriert haben. Also ... es scheint doof, dass ich meinen Code ändern müsste, um mich mit etwas zu verbinden, das einfach abstrahieren sollte, im Gegensatz zur Änderungsfunktionalität. – kddeisz

+0

Sie können nur das Date/Time-Objekt in die Warteschlange stellen. Nichts anderes? AFAIK, ActiveJob ruft tatsächlich Marshal auf, um Ihr Objekt zu serialisieren und benötigt etwas wie den Affen-Patch, von dem Sie sagten, dass er dieses Objekt später abrufen und abrufen kann. Kannst du deinen Mailer posten? – lsdr

Antwort

3

Benötigen Sie wirklich Serialisierung? Wenn es nur ein Time/DateTime-Objekt ist, warum codieren Sie nicht einfach nur Ihren Parameter als Unix-Timestamp-Primitiv?

>> tick = Time.now 
=> 2016-03-30 01:19:52 -0400 

>> tick_unix = tick.to_i 
=> 1459315192 

# Send tick_unix as the param... 

>> tock = Time.at(tick_unix) 
=> 2016-03-30 01:19:52 -0400 

Beachten Sie, dass dies innerhalb einer Sekunde genau ist. Wenn Sie 100% genaue Genauigkeit benötigen, müssen Sie die Zeit in ein Rational konvertieren und sowohl den Zähler als auch den Nenner als Parameter übergeben und dann Time.at(Rational(numerator, denominator) innerhalb des Jobs aufrufen.

>> tick = Time.now 
=> 2016-03-30 01:39:10 -0400 

>> tick_rational = tick.to_r 
=> (1459316350224979/1000000) 

>> numerator_param = tick_rational.numerator 
=> 1459316350224979 

>> denominator_param = tick_rational.denominator 
=> 1000000 

# On the other side of the pipe... 

>> tock = Time.at(Rational(numerator_param, denominator_param)) 
=> 2016-03-30 01:39:10 -0400 

>> tick == tock 
=> true 
+0

Ich weiß, dass es viele Möglichkeiten gibt, dies zu tun, indem ich den Wert ändere. Ich habe mich nur gefragt, ob es einen Weg gibt, dies in Verbindung mit der Serialisierung der anderen Objekte zu tun. Als in der Lage sein, 'my_method (Datum, Zeit, Modell) zu übergeben' und es funktioniert. Zu diesem Zeitpunkt ist es jedoch ziemlich veraltet, weil diese Frage vor fast einem Jahr gestellt wurde. – kddeisz