2015-04-16 9 views
14

Qualcuno sa di un modo pulito per evitare il ActiveJob::SerializationError che si verifica quando si tenta di serializzare un oggetto Date o Time?SerializationError Rails ActiveJob Ora e data

Le due soluzioni che ho avuto finora sono a:

  • chiamata maresciallo/JSON/YAML dump durante il caricamento degli argomenti e poi load indietro nel lavoro (che fa schifo perché ho bisogno di scimmia patchare il lavoro mailer)
  • scimmia di patch Date e Time in questo modo:

/lib/core_ext/time.rb

class Time 

    include GlobalID::Identification 

    def id 
    self.to_i 
    end 

    def self.find(id) 
    self.at(id.to_i) 
    end 
end 

/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 

che aspira anche. Qualcuno ha una soluzione migliore?

+2

È davvero necessario passare solo una data o ora al lavoro (e perché)? Penso che sarebbe meglio passare un ActiveModel come parametro al lavoro, possibilmente contenente un'istanza Data o Ora. (ActiveModels include GlobalID :: Identification in modo che siano serializzabili) – sourcx

+0

No, non è veramente necessario. È solo conveniente. E per di più, ha funzionato con DelayedJob prima di integrare ActiveJob. Quindi ... sembra stupido che avrei bisogno di cambiare il mio codice per integrarlo con qualcosa che dovrebbe semplicemente astrarre anziché cambiare funzionalità. – kddeisz

+0

Accodate solo l'oggetto Data/Ora? Nient'altro? AFAIK, ActiveJob chiama in realtà Marshal per serializzare il tuo oggetto e ha bisogno di qualcosa come la patch della scimmia che hai detto di essere in grado di recuperare e richiamare più tardi questo oggetto. Puoi pubblicare il tuo Mailer? – lsdr

risposta

3

Hai davvero bisogno di serializzazione? Se si tratta solo di un oggetto Time/DateTime, perché non codificare e inviare semplicemente i propri parametri come primitiva del timestamp Unix?

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

Nota questo sarà accurato entro un secondo. Se hai bisogno di precisione esatta al 100% dovrai convertire il tempo in un Rational e passare sia il numeratore che il denominatore come parametri e quindi chiamare Time.at(Rational(numerator, denominator) all'interno del lavoro.

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

So che ci sono molti modi per farlo cambiando il valore, mi stavo chiedendo se c'era un modo per farlo in combinazione con la serializzazione degli altri oggetti. Come essere in grado di passare 'my_method (data, ora, modello)' e farlo funzionare. A questo punto è piuttosto obsoleto perché questa domanda è stata fatta quasi un anno fa. – kddeisz