Making Devise Mailers asynchronous

Devise is an awesome gem, it makes authentication for Rails apps really simple. One problem I faced was trying to make Devise mailers asynchronous. This kinda sorta worked, sometimes emails from devise will come almost immediately, sometimes it won’t come at all. Obviously, inconsistency is Not Good.

I figured the devise-async gem was to blame for this. So I decided to dive into it and see what I could find. Code reading is supposed to make you smarter anyway.

First thing I did was fork the gem, that way a copy appears on my github for me to modify and use. To use my own version of the gem I write this in my gemfile:

gem 'devise-async', git: "git://github.com/hewrin/devise-async.git"

With “hewrin” being my username.

Looking at tests are a good way to find out what a gem/app does. Unfortunately nobody told me about this when I first began diving in. All I did was insert “byebug” everywhere and send a devise email. But first, lets look at the Big Picture.

devise-async is a small gem, all the important stuff happens in the lib folder. To be more specific, the important stuff happens in the devise folder in the lib folder. Lets first look at the async.rb file.

From what I understand, this file is extending the Devise module by adding the Async feature. The file is pretty well commented, so its pretty simple to figure out what it does. The only interesting thing I found was mattr_accessor

mattr_accessor is like attr_accessor, difference is it creates getter/setter methods for modules instead of instances. This makes it easy for people to modify things in the initializers folder in a Rails app. The setup method at the bottom is what allows users to modify the configuration of the gem.

    def self.setup
      yield self

I haven’t encountered this before, it seems doing yield self loads up the whole Module, allowing us access to all mattr_accessor .

The kind people who created the gem even gave us an example:

    Devise::Async.setup do |config|
      config.backend = :sidekiq
      config.queue   = :default

In the example above, config.backend pretty much means Devise::Async.backend. So putting the above in a file in my initializers folder will set Sidekiq as my backend and the queue name as default.

Finally, at the bottom there is a method that adds the Async module to devise, this is what allows us to add devise :async in our model files to make the mailers asynchronous, just like when we add :confirmable to send confirmation emails.

The Devise.add_module method is quite interesting. Below is the source code of the method, taken from Devise:

    def self.add_module(m)
      class_eval <<-METHOD, __FILE__, __LINE__ + 1
        def #{m}?

This…will be discussed in my next post.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s