There are just some days when you want to interact with real data from a Rails application that you wrote. Doing a database dump, saving the output locally, and loading that data in is the ideal method, but once you do that, you’ve got live data locally. This can be a Bad Thing™ if you’re sending email.
Mailers can be triggered in any number of places. A callback, a controller, or an observer could be sitting there, waiting to send off an email to an unsuspecting victim without you being aware. This is one reason why playing with live data is a bit dangerous. There’s luckily an easy workaround.
ActionMailer::Base has an instance method,
recipients, that accepts a string
of email addresses to whom you’ll be sending your message. If we override that
method in the mailer classes we don’t want sending email, we can intercept any
calls and replace recipients if we want.
class ProductMailer < ActionMailer::Base # mailer methods def recipients(*emails) if emails.size == 1 super(MAILER_RECIPIENT_OVERRIDE || emails.first) else super(*emails) end end end
Using Ruby, we overload the recipients method and call
super, passing our
MAILER_RECIPIENT_OVERRIDE constant or the email addresses that were passed.
Because our mailer inherits from
super will relay the
constant or whatever was passed; if the constant is
nil, the recipients will
work normally. However, in our development environment (for example), if that
constant is assigned a string, the email will be delivered to the email instead.
Where does this leave us?
We’re going to want to assign values to this constant for each of our
config/environments/development.rb (or whichever environment
you dumped the live data into), we’ll want to assign this to a string. I like
sending everything to “email@example.com”. Within our other environments, we’ll
want this set to
nil so it doesn’t affect our tests or production site emails.
# config/environments/development.rb MAILER_RECIPIENT_OVERRIDE = "firstname.lastname@example.org" # config/environments/staging.rb MAILER_RECIPIENT_OVERRIDE = "email@example.com" # config/environments/test.rb MAILER_RECIPIENT_OVERRIDE = nil # config/environments/production.rb MAILER_RECIPIENT_OVERRIDE = nil
This solution provides a quick, simple way to override recipients without cluttering up the code and allows a flexible solution when dealing with live data.
There is a caveat, however. You have to do this for every mailer. There are
ways around this (like creating an
ApplicationMailer base class that your
mailers inherit from), but unless you’re dealing with a bunch of mailers,
defining recipients in each is a perfectly acceptable solution.