我可以将delayed_job发送到仅内存的ActiveRecord对象吗?

时间:2015-07-10 23:58:18

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

因为没有实例化邮件服务API密钥,所以我收到了一些未发送的电子邮件。但是, Detail 模型对象保留在数据库中。我不想在数据库中重新创建这些。

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

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

但是我在运行rake任务后注意到Delayed :: Job.all队列中的以下错误:

last_error: "ActiveRecord::RecordNotFound

这是否意味着我将 Detail 对象传入 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

1 个答案:

答案 0 :(得分:1)

我也遇到过这种情况。使用已保存的ActiveRecord::Base子类版本而不是在DJ队列中再次保留完整内容是DJ的优化。我确信他们这样做是因为AR的实例可能很大。

如果您定义的新类与[{1}}感兴趣的字段相同,但继承自Detail ,.类似的东西:

ActiveRecord::Base

现在用一个实例启动作业:

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

更多详细信息:延迟作业 - 特别是方法temp_obj = DetailAsAPlainOldRubyObject.new(detail_params) DetailMailerJob.new.delay.notify_job(temp_obj) - 通过存储delay类(在您的示例中为self),名称来起作用方法(DetailMailerJob)的方法,以及数据库表中参数的序列化表示。 Worker处理从表中出列记录,反序列化参数,并在类上调用该方法。

问题在于序列化。 DJ使用仅编码表名和主键的特殊serializer for ActiveRecord来增加YAML。反序列化表中notify_job的结果。我想他们这样做是为了节省数据库空间和时间。当然,这个技巧只有在find被保存的情况下才有效。 (如果DJ没有保存记录,如果DJ跳过了棘手的序列化,那将是很酷的,但唉它没有。)

在上面链接的代码中注意您的错误消息!它在ActiveRecord失败时引发的异常中使用。

通过使用没有find基础的普通对象,您应该将正常的YAML序列化为字符串。