2015-04-16 4 views
14

Кто-нибудь знает о чистом способе избежать ActiveJob::SerializationError, который возникает при попытке сериализации объекта Date или Time?SerializationError Rails ActiveJob Время и дата

два решений, которые я имел до сих пор является:

  • вызова маршал/JSON/YAML dump при загрузке аргументов, а затем load назад в Иове (который сосет, потому что мне нужно обезьяне патчить почтовик работа)
  • обезьяны патч Date и Time так:

/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 

Который также сосет. У кого-то есть лучшее решение?

+2

Действительно ли необходимо передать только дату или время на работу (и почему)? Я думаю, было бы лучше передать ActiveModel в качестве параметра для задания, возможно, содержащего экземпляр Date или Time. (ActiveModels включают GlobalID :: Идентификация, поэтому они сериализуются) – sourcx

+0

Нет, это не обязательно. Это просто удобно. И вдобавок ко всему, он работал с DelayedJob, прежде чем мы интегрировали ActiveJob. Итак ... кажется глупым, что мне нужно будет изменить свой код, чтобы интегрироваться с чем-то, что просто должно абстрагироваться, а не изменять функциональность. – kddeisz

+0

Вы только ставите в очередь объект Date/Time? Ничего больше? AFAIK, ActiveJob на самом деле называет маршала сериализовать ваш объект и нуждается в чем-то вроде патча обезьяны, который, как вы сказали, сможет восстановить и вспомнить этот объект позже. Можете ли вы разместить свой Mailer? – lsdr

ответ

3

Вам действительно нужна сериализация? Если это всего лишь объект Time/DateTime, почему бы просто не кодировать и не отправлять ваш параметр в качестве примитива временной метки 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 

Обратите внимание: это будет точно в течение одной секунды. Если вам нужна точная точность 100%, вам нужно будет преобразовать время в Rational и передать как числитель, так и знаменатель в качестве параметров, а затем вызвать Time.at(Rational(numerator, denominator) в задании.

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

Я знаю, что есть много способов сделать это, изменив значение, мне просто интересно, есть ли способ сделать это в сочетании с сериализацией других объектов. Как в возможности передать 'my_method (дата, время, модель)' и заставить его работать. На данный момент это довольно устарело, хотя этот вопрос задавался почти год назад. – kddeisz

Смежные вопросы