2015-07-10 47 views
0

所以我有一些电子邮件没有出去,因为没有实例化邮件服务API密钥。但是,详细信息模型对象被保存在数据库中。我不想在数据库中重新创建它们。我可以发送delayed_job一个内存中唯一的ActiveRecord对象吗?

我编写了一个rake任务来发送电子邮件,并且它更容易尝试创建一些临时内存中对象,而不是尝试根据detail_params中的内容找到正确的ActiveRecord对象。然后,我用DetailMailerJob发送的电子邮件,并通过在实例化详细对象。

temp_obj = Detail.new(detail_params) 
    DetailMailerJob.new.delay.notify_job(temp_obj) 

但我运行rake任务后,注意到在延迟:: Job.all队列以下错误:

last_error: "ActiveRecord::RecordNotFound 

这是否意味着只办法,我在通详细对象为DetailMailerJob是先找到数据库实例化的记录? (即,没有在内存中的对象)

编辑:这里是DetailMailer & DetailMailerJob类。

class DetailMailerJob 
     def notify_job(detail) 
     DetailMailer.notify_job(detail).deliver 
     end 
    end 


class DetailMailer < ActionMailer::Base 
    def notify_job(detail) 
    @detail = detail 
    @emailed_to = detail.emailed_to.join(", ") 
    mail(to: detail.emailed_to, subject: "#{detail.full_name} - New Message") 
    end 
end 
+0

如果不知道“DetailMailerJob”中有什么,就不可能回答这个问题。这就是产生错误的原因! – Gene

+0

感谢您的建议基因。更新。 – Nona

回答

1

我也遇到过这个问题。这是对DJ的优化,使用ActiveRecord::Base的已保存版本的子类,而不是将全部内容再次保存在DJ队列中。我相信他们这样做是因为AR的实例可能很大。

如果你定义一个相同的感兴趣的领域DetailActiveRecord::Base继承了一个新类。喜欢的东西:

temp_obj = DetailAsAPlainOldRubyObject.new(detail_params) 
DetailMailerJob.new.delay.notify_job(temp_obj) 

更多细节:

class DetailAsAPlainOldRubyObject 
    attr_accessor :field_a, :field_b, ... 

    def initialize(params) 
    self.field_a = params['field_a'] 
    self.field_b = params['field_b'] 
    ... 
    end 
end 

现在用一个实例启动作业延迟的工作 - 特别是方法delay - 作品存储类的self(在你的榜样DetailMailerJob),方法的名称(notify_job)以及数据库表中参数的序列化表示。工作进程从表中出列记录,反序列化参数,并调用该类的方法。

的问题是序列化。 DJ用特殊的serializer for ActiveRecord来扩充YAML,它只编码表名和主键。反序列化导致表中的find。我想他们这样做是为了节省数据库空间和时间。当然,这个技巧只有在ActiveRecord已被保存时才有效。 (IMO它会很酷,如果DJ跳过棘手的系列化如果记录尚未保存,但可惜事实并非如此。)

在上面的链接请注意,在你的代码的错误信息!它被用于当find失败时引发的异常。

通过使用普通的对象没有ActiveRecord基地,你应该得到正常的YAML序列化的字符串。

相关问题