I use Delayed_job on Ducky Guidance to send our email notifications in the background. I recently switched our authentication gem from authlogic to Devise to take advantage of the baked in password reset functionality (and to allow us to use other built in features down the road as well).
After migrating our users from authlogic to Devise, the first order of business was to set up Delayedjob to send password reset emails in the background. After scouring the web, the most common advice I found was to have Devise utilize delayedjob to do the following:
module Devise module Models module Confirmable handle_asynchronously :send_confirmation_instructions end module Recoverable handle_asynchronously :send_reset_password_instructions end module Lockable handle_asynchronously :send_unlock_instructions end end end
(Forked from robotmay via Stack Overflow)
This code utilizes delayedjob's `:handleasynchronously
wrapper, I was
met with mixed results. More often than not, I was met with
s due to nil objects. The issue was hard to track down,
as I could get it to work sometimes, depending on where the above
snippet was located. I had it working consistently on my laptop by
adding the snippet to the end of myconfig/initializers/devise.rb`
file, but when I tried it on our staging server, the nil objects reared
their heads again.
There is another way to have Devise send its email in the background, and that is by using a custom mailer with Devise. There is a configuration parameter in the Devise initializer that will allow you to set the class you want to use for emails. I went about using the following custom emailer:
class PasswordResetMailer < Devise::Mailer def reset_password_instructions(record) Delayed::Job.enqueue PasswordResetJob.new(record.id) end end
The above code inherits from
Devise::Mailer and overrides the
reset_password_instructions method (which is the only one I care about
right now). I used Delayed_job to enque a custom job called
class PasswordResetJob < Struct.new(:id) def perform user = User.find(id) Devise::Mailer.reset_password_instructions(user).deliver end end
The job takes the user's id, retrieves that record, and uses the default Devise mailer to reset the password and send the user the reset instructions.
After setting up the custom mailer and job, I just had to configure
devise to use that mailer. I added the following line to my
Devise.setup do |config| #... config.mailer = "PasswordResetMailer" #... end
And was on my way. The mailer works perfectly, sending password resets in the background without error.