deviseで送信されるメールを非同期処理にする方法


はじめに

railsで作ったアプリケーションにdeviseを導入していますが、会員登録時などに送信するメールを非同期処理でおこないたいと思います。
メール送信処理でエラーが発生しても画面操作が続けられることがメリットです。
今回は非同期処理にdelayed_jobを使用します。
他にはside_kiqを使う方法もあります。

前提

  • deviseが使用できること。

devise-asyncのインストール

以下のgemをGemfileに追加し、bundle installしてください。

Gemfile
gem 'devise-async'

非同期処理を有効にするため、devise-async.rbを修正します。

config/initializers/devise-async.rb
Devise::Async.setup do |config|
  config.enabled = true
end

queue_adapterdelayed_jobを指定します。

config/application.rb
module [アプリ名]
  class Application < Rails::Application
    # 省略

    config.active_job.queue_adapter = :delayed_job
  end
end

Mailerをカスタマイズ

以下のようにDevise::Mailerを継承したカスタマイズクラスを作成します。

必要に応じてメソッドをオーバーライドしてください。
Devise::Mailerのメソッド

app/mailers/user_mailer.rb
class UserMailer < Devise::Mailer
  default from: '[email protected]'

  def confirmation_instructions(record, token, opts = {})
    @token = token
    devise_mail(record, :confirmation_instructions, opts)
  end
end

devise.rbでカスタマイズしたMailerを指定します。

config/initializers/devise.rb
Devise.setup do |config|
  config.mailer = 'UserMailer'

  # 省略
end

delayed_jobのインストール

delayed_jobに関するgemをbundle installします。

Gemfile
gem 'delayed_job_active_record'

# デプロイ先でデーモンとして動かすのに必要
gem 'daemons'

delayed_jobテーブルを作成します。

rails g delayed_job:active_record
rake db:migrate

Jobをスタートさせます。

bin/delayed_job start

正常に起動できているか確認します。

$ ps aux | grep delayed_job
user 16788   0.0  2.2  4621728 183972   ??  S     2:16PM  10:24.78 delayed_job  
user 20824   0.0  0.0  4286716    720 s002  S+    7:34PM   0:00.01 grep delayed_job

Capistranoによるデプロイ

Capistrano用のgemを追加し、bundle installします。

Gemfile
gem 'capistrano3-delayed-job'

Capfileには以下のrequire文を追加してください。

Capfile
require 'capistrano/delayed-job'

参考

Ruby on Rails + Action Mailerで非同期メール送信機能の実装