Skip to content

Instantly share code, notes, and snippets.

@jasonkarns
Last active May 27, 2021 15:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jasonkarns/0d4325db01e8370c7c3af422dac757c5 to your computer and use it in GitHub Desktop.
Save jasonkarns/0d4325db01e8370c7c3af422dac757c5 to your computer and use it in GitHub Desktop.
A helper to generate mailer previews automatically (or more easily) for each action that exists on the mailer.
module MailerPreviewHelper
extend ActiveSupport::Concern
included do
# Allows a mailer preview to override `params` method (either class or instance level)
# to define the hash that will be passed to the mailer by default by the `preview` helper.
class_attribute :params, default: {}, instance_accessor: false
mailer.instance_methods(false).each do |action|
define_method(action) { mailer.with(**params).send action }
end
end
class_methods do
def mailer
@mailer ||= preview_name.classify.constantize
end
end
private
# The associated Mailer class for this Preview
def mailer
self.class.mailer
end
# Derives the action (message) name from the caller and invokes it on the mailer class
def preview(*args)
action = caller_locations(1..1).first.base_label
mailer.with(**params).send action, *args
end
# Explicitly defined instead of leveraging class_attribute instance methods
# because we need to override the `params` method defined by ActionMailer::Preview.
# Also, we don't want the writer/predicate or for it to be public
# b/c that would add them to the mailer preview message listing.
# TODO make params persist for both header frame and body frame requests
def params
self.class.params
end
end
class MyMailer < ActionMailer::Base
before_action do
@user = params[:user]
end
def welcome
end
def welcome_the_second(arg)
end
def goodbye
end
end
class MyMailerPreview
include MailerPreviewHelper
# welcome is defined automatically!
# same as: MyMailer.with(user: ...).welcome
# goodbye is defined automatically!
# same as: MyMailer.with(user: ...).goodbye
def welcome_the_second
preview("but with args")
end
def completely_different
mailer.with(something: "different").goodbye
end
def self.params
{ user: FactoryBot.create(:user) }
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment