【问题标题】:Rails - Send all emails with delayed_job asynchronouslyRails - 异步发送所有带有delayed_job的电子邮件
【发布时间】:2014-02-04 15:08:00
【问题描述】:

我正在使用delayed_job,我对此非常满意(尤其是workless 扩展)。

但我想将我的应用中的所有封邮件设置为异步发送。

确实,为邮寄者提供的解决方案

# without delayed_job
Notifier.signup(@user).deliver

# with delayed_job
Notifier.delay.signup(@user)

不适合我,因为:

  • 不容易维护
  • 从 gems 发送的邮件不会异步发送(devisemailboxer

我可以使用这种扩展程序https://github.com/mhfs/devise-async,但我宁愿立即为整个应用找出解决方案。

我不能扩展 ActionMailer 以覆盖 .deliver 方法(就像这里的 https://stackoverflow.com/a/4316543/1620081 但它已经 4 岁了,就像我在该主题上找到的几乎所有文档一样)?

我正在使用带有 activerecord 的 Ruby 1.9 和 Rails 3.2。

感谢支持

【问题讨论】:

  • 您尝试过自己的建议吗?不过,您必须覆盖 Mail::Message 对象

标签: ruby-on-rails ruby-on-rails-3 asynchronous devise actionmailer


【解决方案1】:

一个简单的解决方案是在 Notifier 对象上编写一个实用方法,如下所示:

class Notifier

  def self.deliver(message_type, *args)
    self.delay.send(message_type, *args)
  end

end

发送注册邮件如下:

Notifier.deliver(:signup, @user)

实用程序方法提供了一个点,如果需要,您可以用 resque 或 sidekiq 解决方案替换延迟作业。

【讨论】:

  • 我喜欢这种方式。接近我最终做的事情,尽管我没有在这里更新,因为它没有准确回答“默认情况下如何将整个邮件程序异步?”的问题
【解决方案2】:

如果您已完成 ActiveJob 和并发库设置 documentation here。最简单的解决方案是覆盖您的设备 send_devise_notification 与事务邮件相关的实例方法,如所示 here

class User < ApplicationRecord
  # whatever association you have here
  devise :database_authenticatable, :confirmable
  after_commit :send_pending_devise_notifications
  # whatever methods you have here

 protected
  def send_devise_notification(notification, *args)
    if new_record? || changed?
      pending_devise_notifications << [notification, args]
    else
      render_and_send_devise_message(notification, *args)
    end
  end

  private

  def send_pending_devise_notifications
    pending_devise_notifications.each do |notification, args|
      render_and_send_devise_message(notification, *args)
    end

    pending_devise_notifications.clear
  end

  def pending_devise_notifications
    @pending_devise_notifications ||= []
  end

  def render_and_send_devise_message(notification, *args)
    message = devise_mailer.send(notification, self, *args)

    # Deliver later with Active Job's `deliver_later`
    if message.respond_to?(:deliver_later)
      message.deliver_later
    # Remove once we move to Rails 4.2+ only, as `deliver` is deprecated.
    elsif message.respond_to?(:deliver_now)
      message.deliver_now
    else
      message.deliver
    end
  end

end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-22
    • 1970-01-01
    • 2015-03-17
    • 2014-01-28
    相关资源
    最近更新 更多