Resque and Resque_mailer with Devise

拈花ヽ惹草 提交于 2020-01-06 07:53:07

问题


I am implementing background email processing with Resque using the resque_mailer gem (https://github.com/zapnap/resque_mailer). I was able to get it to work for all my emails except the ones sent by Devise.

I went through a bunch of SO questions, and blog posts (for instance http://teeparham.posterous.com/send-devise-emails-with-resque) but could not find a way to get it to work.

What are the precise steps to follow to get resque_mailer to work with Devise?


回答1:


I'd take a look at devise-async. Looks like it fits your use case. Devise Async




回答2:


I went through tee's answer and several resources online, but couldn't find a working solution.

After a few days of reading through resque-mailer and devise code, a solution that worked for me. Thanks to tee for gist which put me in right direction.

Assuming your app/mailers/application_mailer.rb looks similar to

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

In config/initializers/devise.rb

Devise.parent_mailer = "ApplicationMailer" 

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

In the resource class which uses devise, overwrite the send_devise_notification method to send resource class and id instead of object to prevent marshalling

# 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

Finally, in app/mailers/devise_resque_mailer.rb, fetch the record again from the database and continue

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

I feel this approach is a better than using devise-async as all the mails go through same code path. Its easier to control and overwrite if needed.



来源:https://stackoverflow.com/questions/14286601/resque-and-resque-mailer-with-devise

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!