首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MonkeyPatching ActiveJobs

MonkeyPatching ActiveJobs
EN

Stack Overflow用户
提问于 2014-12-23 23:51:50
回答 2查看 688关注 0票数 4

我有一个问题,猴子修补部分ActiveJobs。我在config/initializers/extensions/argements.rb中有以下代码

代码语言:javascript
复制
module ActiveJob
  module Arguments
    TYPE_WHITELIST = [ Date, DateTime, Time, NilClass, Fixnum, Float, String, TrueClass, FalseClass, Bignum ]
  end
end

基本上,我试图添加对日期/时间对象的基本支持,以便在由ActiveJob创建的ActionMailer#deliver_later中使用。

在加载rails应用程序时,我可以看到我的白名单已经加载,但是当我在邮件程序上调用deliver_later方法时,原始的白名单会覆盖我的修补程序。

代码语言:javascript
复制
#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::参数,在调用deliver_later之前不会加载,因此在我的修补程序之后加载并重写它,尽管我不知道如何修复它。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-01-26 11:06:07

编辑:不要使用,请参阅https://stackoverflow.com/a/50743819/3293310

这个怎么样?

代码语言:javascript
复制
module ActiveJob
  module Arguments 
    remove_const(:TYPE_WHITELIST)
    TYPE_WHITELIST = [ Date, DateTime, Time, NilClass, Fixnum, Float, String, TrueClass, FalseClass, Bignum ]
  end
end

然后,正如注释中所说的,您应该扩展这个模块:

代码语言:javascript
复制
module ActionMailer 
  class DeliveryJob < ActiveJob::Base 
    extend ActiveJob::Arguments 
  end
end

如果您使用的是ruby 2+,一个更好的方法是tu使用改进。不幸的是,您不能用改进的(请阅读Matz的评论)更改常量

票数 0
EN

Stack Overflow用户

发布于 2018-06-07 14:28:46

Pak给出的解决方案可能是危险的!

TL;DR :它在嵌套散列中用时间对象中断,就像反序列化期间一样,它们将作为字符串返回。

因此,在生产中,您实际上希望能够将时间序列化为字符串,并将“时间字符串”反序列化为时间对象。如果只是将时间添加到类型白名单中,序列化和反序列化在常规参数中可能工作得很好,但如果以散列参数发送时间对象,则会中断时间对象,编写失败的测试几乎是不可能的。

相反,按照那里描述的使用GlobalIds对时间类进行分类,这是序列化与ActiveJob一起使用的任何param的常规方法。

基本上,您可以这样修补您的类。

代码语言:javascript
复制
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

因此,可以正确地序列化/反序列化参数。

代码语言:javascript
复制
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有效果,但这比没有aye要好吗?

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27629697

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档