MonkeyPatching ActiveJobs

雨燕双飞 提交于 2019-12-04 13:56:42

What about this ?

module ActiveJob
  module Arguments 
    remove_const(:TYPE_WHITELIST)
    TYPE_WHITELIST = [ Date, DateTime, Time, NilClass, Fixnum, Float, String, TrueClass, FalseClass, Bignum ]
  end
end

Then, as said in the comments you should extend this module :

module ActionMailer 
  class DeliveryJob < ActiveJob::Base 
    extend ActiveJob::Arguments 
  end
end

A better way if you're using ruby 2+ would be tu use Refinements. Unfortunately, you can't change constants with refinements (read Matz' comment here)

The solution given by @Pak can be dangerous !

TL;DR : it breaks with time objects in nested hashes, as during deserialization, they will be returned as string

So in production, you actually want to be able to serialize time to string and deserialize "time strings" as time objects. If you just add Time to the type whitelist, serialization and deserialization might work well enough in regular params, but if you send your time object in a hash argument, it will break, and it will become almost impossible to write a failing test.

Instead, monkeypatch your time classes as described there using GlobalIds, which is the regular way of serializing any param for use with ActiveJob

Basically you can patch your classes this way

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

As a result, you can properly serialize/deserialize your arguments

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

Note that this has for effect of converting AS:TWZ to plain old Time but this is better than nothing aye ?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!