Most of the web applications today need to send some kind of email. In Ruby on Rails, this is an easy task. Just use the Action Mailer, create the email content, set up the SMTP configuration and you are ready to go.
The hardest part of this process is the content creation. Especially if you are building a multi-language application, seeing the big picture just from the source code can be quite hard. Fortunately, Rails provides a way to see how these emails look right in a web browser, using the Action Mailer Previews. Just create a class that inherits from the ActionMailer::Preview
and call the required mailer action.
# test/mailers/previews/user_mailer_preview.rb
class UserMailerPreview < ActionMailer::Preview
def confirmation
user = User.new(email: "[email protected]")
UserMailer.with(user: user).confirmation
end
end
However, sometimes your mailer expects the ID of a record in the database, not the object itself. And sometimes you need to prepare this record, for example to create a new email confirmation token.
# test/mailers/previews/user_mailer_preview.rb
class UserMailerPreview < ActionMailer::Preview
def confirmation
user = User.first
user.prepare_token!(:confirmation)
UserMailer.with(user_id: user.id).confirmation
end
end
But this should be just a temporary change. Sure, you can wrap the whole method in a database transaction and use the database rollback command. But… How exactly?
Fortunately, there is an easy way to accomplish this using some Rails monkey patching. Just create the following module:
# lib/core_extensions/mailer_preview_rollback
module CoreExtensions
module MailerPreviewRollback
def preview
ActiveRecord::Base.transaction do
super
raise ActiveRecord::Rollback
end
end
end
end
Create an initializer in your Ruby on Rails application and prepend this module:
# config/initializers/mailer_preview_rollback.rb
Rails.configuration.to_prepare do
require "core_extensions/mailer_preview_rollback"
Rails::MailersController.prepend CoreExtensions::MailerPreviewRollback
end
And voila! All of your mailer previews are now safely wrapped in a database transaction.