Flexibly create notifications that can be sent across multiple mediums, like email, SMS, and push.
There are two types of objects: Notification and Medium
Notification is a parent class for different types of notifications. For example, a subclass may be: CalendarEventChangeNotification which is created for every user that is notified of a calendar event change.
Mediums::Base is a parent class for different types of communication mediums. For example, email, SMS, or push.
There are four steps to wire up a notification:
- Add Medium(s)
- Add Notification
- Write notification template for each medium
- Wire up callback to send notifications
rails g medium Email
rails g medium Sms
After making some changes to the generated file to suit our needs, we end up with something like the following:
module Mediums
class EmailMedium < NotificationEngine::Mediums::Base
attr_reader :email, :subject, :body
def after_init(args = {})
@email = args[:email]
@subject = args.fetch(:subject, parse_template(:subject))
@body = args.fetch(:body, parse_template(:body))
end
def deliver
NotificationMailer.basic_notification(message_args).deliver_later
end
def slug
'email'
end
private
def required_attrs
[:email]
end
def message_args
@message_args ||= {
to: email,
subject: subject,
body: body
}
end
end
endmodule Mediums
class SmsMedium < NotificationEngine::Mediums::Base
attr_reader :body, :mobile_phone
def after_init(args = {})
@mobile_phone = args[:mobile_phone]
@body = args.fetch(:body, parse_template(:body))
end
def deliver
# hook up Twilio or other SMS service here
# we can pass in mobile_phone and body as args
end
def slug
'sms'
end
private
def required_attrs
[:mobile_phone]
end
end
endThe only two required methods for a Medium are slug and deliver. You'll see why the slug is important here in a bit.
rails g notification NewTeamMember
class NewTeamMemberNotification < NotificationEngine::Notification
def mediums
[:email, :sms]
end
def data
{
email: 'ned@example.com',
mobile_phone: '123-456-1828',
recipient: {
name: 'Ned Stark'
},
new_user: {
name: 'Jon Snow'
}
}
end
endIn this case, email is used by the email medium and mobile_phone is used by sms medium. The other information in data will be used by our template.
In config/locales/en.yml:
en:
notifications:
new-team-member-notification:
email:
subject: '{{ new_user.name }} was just created'
body: >
Hi {{ recipient.name }},
A new user named {{ new_user.name }} was added to your team. Please login to review the new user.
another-example-notification:
all:
body: An example body that would work across all mediums for this notificationclass User < ApplicationRecord
after_create :send_notifications
def send_notifications
team_members.each do |team_member|
notification = NewTeamMemberNotification.create(
recipient: team_member,
notifiable: self
)
notification.deliver
end
end
endGemfile:
gem 'notification_engine'bundle
The gem is available as open source under the terms of the MIT License.