0

我正在使用 resque_mailer gem (https://github.com/zapnap/resque_mailer) 使用 Resque 实现后台电子邮件处理。我能够让它适用于我所有的电子邮件,除了由 Devise 发送的电子邮件。

我经历了一堆 SO 问题和博客文章(例如http://teeparham.posterous.com/send-devise-emails-with-resque),但找不到让它工作的方法。

让 resque_mailer 与 Devise 一起工作的具体步骤是什么?

4

2 回答 2

1

我在网上浏览了tee 的答案和几个资源,但找不到有效的解决方案。

经过几天阅读 resque-mailer 并设计代码后,一个对我有用的解决方案。感谢 tee 的要点,它让我朝着正确的方向前进。

假设您的app/mailers/application_mailer.rb外观类似于

class ApplicationMailer < ActionMailer::Base
  include Resque::Mailer # This will add a `self.perform` class method, which we will overwrite in DeviseResqueMailer
end

config/initializers/devise.rb

Devise.parent_mailer = "ApplicationMailer" 

Devise.setup do |config|
  config.mailer = 'DeviseResqueMailer'
end 

在使用设计的资源类中,覆盖send_devise_notification发送资源类和id而不是对象的方法,以防止编组

# app/models/user.rb
protected    
def send_devise_notification(notification, *args)
  # Based on https://github.com/zapnap/resque_mailer/blob/64d2be9687e320de4295c1bd1b645f42bd547743/lib/resque_mailer.rb#L81
  # Mailer may completely skip Resque::Mailer in certain cases - and will fail as we write custom handle in DeviseResqueMailer assuming mails are handled via resque
  # So in those cases, don't retain original devise_mailer so things work properly
  if ActionMailer::Base.perform_deliveries && Resque::Mailer.excluded_environments.exclude?(Rails.env.to_sym)
    # Originally devise_mailer.send(notification, self, *args).deliver
    # Modified to ensure devise mails are safely sent via resque
    resource_id, resource_class = self.id, self.class.name
    devise_mailer.send(notification, {resource_id: resource_id, resource_class: resource_class}, *args).deliver
  else
    super
  end
end

最后,在 中app/mailers/devise_resque_mailer.rb,再次从数据库中获取记录并继续

class DeviseResqueMailer < Devise::Mailer

  def self.perform(action, *args)
    # Hack to prevent RuntimeError - Could not find a valid mapping for admin.attributes
    record_hash = args.shift
    record = record_hash["resource_class"].constantize.find(record_hash["resource_id"])
    args.unshift(record)
    super # From resque-mailer
  end
end

我觉得这种方法比使用 devise-async 更好,因为所有邮件都通过相同的代码路径。如果需要,它更容易控制和覆盖。

于 2015-10-14T00:42:48.040 回答
0

我会看看设计异步。看起来它适合您的用例。设计异步

于 2013-01-11T21:40:31.347 回答