SerializationError Rails ActiveJob 时间和日期

15

有人知道避免尝试序列化DateTime对象时发生ActiveJob::SerializationError的简单方法吗?

我迄今为止的两个解决方案是:

  • 在加载参数时调用Marshal/JSON/YAML dump,然后在作业中load回来(这很糟糕,因为我需要猴子补丁邮件发送作业)
  • 像这样猴子补丁DateTime

/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作为作业的参数进行传递,其中可能包含日期或时间实例。(ActiveModels包括GlobalID :: Identification,因此它们是可序列化的) - sourcx
不,这并不是必须的。这只是方便而已。而且,在我们集成ActiveJob之前,它可以与DelayedJob一起使用。所以...我觉得很蠢,我需要改变我的代码才能与某些东西集成,这些东西只是为了抽象而不是改变功能。 - kddeisz
你只是将日期/时间对象加入队列吗?没有别的了吗?据我所知,ActiveJob实际上调用Marshal来序列化你的对象,并且需要像你说的那样的猴子补丁才能够在以后检索和调用此对象。你能发一下你的Mailer吗? - lsdr
@kddeisz 还有一种“白名单”方法:https://dev59.com/mYbca4cB1Zd3GeqPUlcc - lsdr
你能举个例子说明你是如何将作业加入队列的吗? - Max Filippov
1个回答

4

你真的需要序列化吗?如果只是一个时间/日期对象,为什么不将其编码并将参数作为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

请注意,这个时间戳的精度可以达到秒级。如果您需要百分之百的准确性,您需要将时间转换为一个有理数,并将分子和分母作为参数传递给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

我知道有很多方法可以通过更改值来实现,我只是想知道是否有一种方法可以与其他对象的序列化相结合来实现。比如能够传递 my_method(date, time, model) 并使其正常工作。不过现在这个问题已经过时了,因为它是在将近一年前提出的。 - kddeisz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接