我正在使用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.我对修复我的猴子补丁并不感兴趣,因为我希望有一个正确的解决方案。
答案 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