3

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

创建记录时,明文密码在 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。我对修复我的猴子补丁也不是很感兴趣,因为我希望有一个适当的解决方案

4

1 回答 1

2

在延迟作业 3.x 中,最好的方法是覆盖 ActiveRecord 类上的一些方法,然后强制 Psych YAML 反序列化器从序列化数据中加载 ActiveRecord 对象。默认情况下,延迟作业仅使用反序列化的 id,然后从数据库加载 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
于 2013-03-26T00:13:49.163 回答