This post is part of a series of 31 Rails 4 articles being released each day in December 2012.
Since Rails 4 has introduced a Queue into the framework, a primary candidate to take advantage of it was Action Mailer.
By default, Action Mailer will set all mailers inheriting from
ActionMailer::Base to use
ActiveSupport::SynchronousQueue. This provides Rails 3 developers the exact same interface they are used to, as all emails are delivered synchronously.
Action Mailers are configured by default to use the application queue,
Rails.queue. To enable asynchronous mailers, set
production.rb to a non-synchronous queue, such as
# production.rb config.queue = ActiveSupport::Queue.new
You can also use a different queue globally for all your mailers via the configuration option
# production.rb config.queue = ActiveSupport::Queue.new config.action_mailer.queue = Sidekiq::Client::Queue.new
Finally, you are able to assign a queue to a specific mailer through the
class SubscriptionMailer < ActionMailer::Base self.queue = MailerQueue.new ... end
Preparing your mailers for Queues
Queues such as Resque or Sidekiq, persist jobs as JSON objects. This means that if you are using one of these queues, you must ensure your mailer arguments can be marshalled to JSON.
For example, instead of passing an Active Record model to a mailer:
You would pass an identifier:
So that your mailer can query the database for the object:
class SubscriptionMailer < ActionMailer::Base def welcome(user_id) @user = User.find(user_id) mail(to: @user.email, subject: 'Thanks for subscribing!') end end
There is also an added benefit of querying for records from queue jobs. It ensures you are working with the most up to date version of your model, eliminating the chance of stale data being used.