Skip to content

Instantly share code, notes, and snippets.

@joelvh
Last active December 11, 2015 23:58
Show Gist options
  • Save joelvh/4679944 to your computer and use it in GitHub Desktop.
Save joelvh/4679944 to your computer and use it in GitHub Desktop.
Easily preview email templates in your browser by adding a route for MailView email previews in your Rails app using this helper class. You can specify which mailers and which email templates to use, as well as what sample data to use.
### CUSTOM CLASS WITH MAILERS TO PREVIEW ###
class EmailPreviews < MailerPreview::Engine
mailer NotificationMailer do
# specify a block that returns the arguments used for this mailer
preview(:new_follower) { User.last }
# make sure I didn't miss any email templates for this mailer
assert_full_coverage!
end
mailer Devise::Mailer do
preview(:confirmation_instructions) { User.last }
preview(:reset_password_instructions) { User.last }
preview(:unlock_instructions) { User.last }
#assert_full_coverage!
end
end
### PLUMBING ###
module MailerPreview
class PreviewEvaluator
def self.run(mailer_class, method_name, &block)
config = self.new
result = config.instance_eval(&block)
# if the block called the "arguments" method we have explicit args,
# otherwise we use the return value of the block if there is one
method_args = config.arguments || (result && Array.wrap(result))
mailer_class.send(method_name, *method_args)
end
def arguments(*args)
@arguments = args if args.any?
@arguments
end
end
class MailerSetup
def self.run(*args, &block)
self.new(*args).instance_eval(&block)
end
attr_reader :preview_class, :mailer_class
def initialize(preview_class, mailer_class)
@preview_class = preview_class
@mailer_class = mailer_class
@method_names = Set.new
end
# specify a template to preview, the block returns the arguments to use for the mailer method
def preview(method_name, &block)
@method_names << method_name = method_name.to_s.to_sym
config = self
preview_class.send :define_method, :"#{mailer_class.name.gsub(/:+/, '_').underscore}_#{method_name.to_s.underscore}" do
PreviewEvaluator.run(config.mailer_class, method_name, &block)
end
end
# ensure that all templates for a mailer have been setup to be previewed
def assert_full_coverage!
remaining = mailer_class.public_instance_methods - mailer_class.superclass.public_instance_methods - @method_names.to_a
if remaining.any?
raise "The following #{mailer_class.name.gsub(/:+/, ' ').titleize}s are missing: #{remaining.join(', ')}"
end
end
end
class Engine < MailView
def self.mailer(klass, &block)
MailerSetup.run(self, klass, &block)
end
end
end
MyRailsApp::Application.routes.draw do
mount EmailPreviews => '/email_previews', :as => :email_previews
root :to => 'welcome#index'
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment