具有自定义属性的延迟作业

时间:2012-04-18 13:05:24

标签: ruby-on-rails-3 delayed-job

我正在使用ActiveRecord和Rails 3.2.3延迟作业3.0.2。我有一个使用has_secure_password mixin的User模型,因此密码只加密存储。现在我想使用延迟作业发送欢迎电子邮件,其中应包含未加密密码的副本。

创建记录时,明文密码为User#password。但延迟作业似乎只序列化/反序列化记录的id,并通过执行User.find(X)创建模型的新实例。这样我的纯文本密码就会丢失,用户在他的电子邮件中会输入一个空密码。

如何告诉延迟作业序列化/反序列化自定义“虚拟”属性,否则这些属性不存储在数据库中?

这是我推迟工作2.x的猴子补丁,效果很好。

class ActiveRecord::Base
  def self.yaml_new(klass, tag, val)
    klass.find(val['attributes']['id']).tap do |m|
      val.except("attributes").each_pair{ |k, v| m.send("#{k}=", v) }
    end
  rescue ActiveRecord::RecordNotFound
    raise Delayed::DeserializationError
  end
end

它不适用于延迟作业3.x.我对修复我的猴子补丁并不感兴趣,因为我希望有一个正确的解决方案

1 个答案:

答案 0 :(得分:2)

在延迟作业3.x中,最好的方法是覆盖ActiveRecord类上的一些方法,然后强制Psych YAML反序列化器从序列化数据加载ActiveRecord对象。默认情况下,延迟作业仅使用反序列化的ID,然后从DB加载ActiveRecord对象。所以,假设我有一个名为ShipmentImport的ActiveRecord类,我想要一个名为'user_id'的attr_accessor来处理延迟的作业序列化/反序列化。这就是我要做的。

在ShipmentImport ActiveRecord类中,添加:

def encode_with(coder)
  super
  coder['user_id'] = @user_id
end

def init_with(coder)
 super
  @user_id = coder['user_id']
  self
end

在应用程序的初始化程序中,为ActiveRecord类添加此项:

Psych.load_tags[['!ruby/ActiveRecord', ShipmentImport.name].join(':')] = ShipmentImport