我有一个问题猴子修补ActiveJobs的一部分。我在config / initializers / extensions / arguements.rb
中有以下代码module ActiveJob
module Arguments
TYPE_WHITELIST = [ Date, DateTime, Time, NilClass, Fixnum, Float, String, TrueClass, FalseClass, Bignum ]
end
end
基本上,我正在尝试添加对Date / Time对象的基本支持,以便在ActionMailer创建的ActiveJob中使用#deliver_later
加载rails应用程序后,我可以看到我的白名单已加载,但是当我在邮件程序上调用deliver_later方法时,原始白名单会覆盖我的补丁。
#List is correct when app loads
2.1.2 :002 > ActiveJob::Arguments::TYPE_WHITELIST
=> [Date, DateTime, Time, NilClass, Fixnum, Float, String, TrueClass, FalseClass, Bignum]
#List is overridden by default list in ActiveJobs after running #deliver_later
2.1.2 :005 > ActiveJob::Arguments::TYPE_WHITELIST
=> [NilClass, Fixnum, Float, String, TrueClass, FalseClass, Bignum]
如何制作修改后的白名单?我很确定错误源于原始的ActiveJob :: Arguments在调用deliver_later之前没有加载,因此在我的补丁之后加载并覆盖它,虽然我不知道如何修复它。
答案 0 :(得分:0)
@Pak给出的解决方案可能很危险!
TL; DR:它在嵌套哈希中与时间对象断开,因为在反序列化期间,它们将作为字符串返回
因此,在制作中,您实际上希望能够将时间序列化为字符串和反序列化"时间字符串"作为时间对象。如果你只是将Time添加到类型白名单中,序列化和反序列化可能在常规参数中运行得很好,但是如果你在哈希参数中发送你的时间对象,它将会中断,并且几乎不可能编写失败的测试。 / p>
相反,使用GlobalIds按照there所描述的方式对时间类进行monkeypatch,这是序列化任何用于ActiveJob的param的常规方法
基本上你可以这样修补你的课程
class Time
include GlobalID::Identification
alias_method :id, :to_i
def self.find(seconds_since_epoch)
Time.at(seconds_since_epoch.to_i)
end
end
class ActiveSupport::TimeWithZone
include GlobalID::Identification
alias_method :id, :to_i
def self.find(seconds_since_epoch)
Time.zone.at(seconds_since_epoch.to_i)
end
end
因此,您可以正确地序列化/反序列化您的参数
arguments = [1, { start: Time.now, end: 1.day.ago }]
serialized_arguments = ActiveJob::Arguments.serialize(arguments)
# => [1,
# {"start"=>{"_aj_globalid"=>"gid://my-job-glasses/Time/1528381306"},
# "end"=>{"_aj_globalid"=>"gid://my-job-glasses/Time/1528294906"},
# "_aj_symbol_keys"=>["start", "end"]}]
deserialized_arguments = ActiveJob::Arguments.deserialize(serialized_arguments)
# => [1, {:start=>"2018-06-07T16:21:46.000+02:00", :end=>"2018-06-06T16:21:46.000+02:00"}]
deserialized_arguments.last[:start].class # => Time
请注意,这会将AS:TWZ
转换为普通的Time
,但这比什么都好?
答案 1 :(得分:-1)
这个怎么样?
module ActiveJob
module Arguments
remove_const(:TYPE_WHITELIST)
TYPE_WHITELIST = [ Date, DateTime, Time, NilClass, Fixnum, Float, String, TrueClass, FalseClass, Bignum ]
end
end
然后,如评论中所述,您应该扩展此模块:
module ActionMailer
class DeliveryJob < ActiveJob::Base
extend ActiveJob::Arguments
end
end
如果您使用ruby 2+,更好的方法是使用 Refinements 。遗憾的是,您无法使用细化(read Matz' comment here)
更改常量