-
Notifications
You must be signed in to change notification settings - Fork 1
notify_on
The NotifyOn gem revolves around calls to notify_on
with your app's models, as:
notify_on(action, options = {})
Let's take a look at the action and options. Note that we use the term trigger a bit here. The trigger is the object that triggers the notification, or an instance of the model in which you called notify_on
.
The action is a symbol as either :create
, :save
, or a custom conditional method that returns a boolean.
Using :create
will fire the notification during the after_create
callback, while :save
and any custom conditional method run during the after_save
callback.
While there exists an :if
and :unless
option (see below), a custom conditional is a way to elevate a if conditional.
In other words, say you want a notification to be triggered after save, but only when a certain condition is true. Instead of using :save
, you can use a method that returns whether or not that condition is true.
You may want to take advantage of Active Record Dirty's dynamic methods, where you can check if an attribute changed. For example, say we have a state
attribute that tracks the current state of an object, we can use state_changed?
, like so:
notify_on :state_changed? # other options ...
You can also write your own custom methods, for example:
notify_on :public_and_active? # other options ...
def public_and_active?
# assuming we have "public?" and "active?" methods ...
public? && active?
end
There are a handful of options, and it's important to understand how each works so you have control over where your notifications are created or updated.
The following section runs through each option and any nuances you may encounter using that option. Scroll to the bottom of this page to see an example.
Required as a Symbol
.
It should represent to whom the notification is sent, as either an Active Record object or a collection of Active Record objects.
It is typically an association on the trigger (most often it is something like User
), but it can be a method that returns an Active Record object.
Optional as a Symbol
.
It should represent from whom the notification is sent, as an Active Record object.
Like :to
, it is typically an association on the trigger (most often it is something like User
), but it can be a method that returns an Active Record object.
Required as an interpolated String
.
The message is meant to be a brief description of the notification.
Required as a String
using interpolation or dynamic link generation.
The link is meant to be a reference link for the recipient (:to
) to access the trigger.
Optional as a Symbol
.
The symbol should reference a conditional method on the trigger that returns a boolean. This is an additional way to control that a notification be created only under a certain condition.
:if
must return false
to prevent the notification. If it returns true
or is missing, the notification will be triggered.
:unless
must return true
to prevent the notification. If it returns false
or is missing, the notification will be triggered.
However, if both options are specified and :if
returns false
OR :unless
returns true
, the notification will not be triggered. (And remember that the action
must also be true
if you've used a conditional method there.)
Optional as a Hash
or Boolean
.
This option specifies whether or not to send an email with the notification, and how it should be sent. If it is missing, nil
, or false
, an email will not be sent.
If you pass :email
as a Hash
, you have the following options:
-
from
: The default email address to send the email from. If omitted, it usesNotifyOn.configuration.default_email
. -
template
: The name of the email template to render. It defaults tonotify
. See Override Default Email Message for more information. -
unless
: ASymbol
representing a conditional method (on the trigger) returning a boolean. If this method returnstrue
, the email will not be sent, assuming email is enabled. -
attachments
: AHash
of key-value pairs that represent a filename-file combination. Both the filename and file resolve to calling a method on the trigger. If the filename method is not found, it will fall back to the plain text key. If the file method is not found, the mailer will throw an error. See below for example usage. -
save_id
: ABoolean
that, if set totrue
, will attempt to save the email'sMessage-ID
header to amessage_id
column on the trigger.
If you have default options set for email (in your initializer), you can simply set :email
to true
and it will use the default settings.
Optional as a Hash
or Boolean
.
This option specifies whether or not to use Pusher to send a real-time event along with the notification, and how that event should be sent. If it is missing, nil
, or false
, it will fallback to its default settings in your initializer (only if you set them).
If :pusher
is set to true
, the default settings are used. Or, if any particular pusher setting is omitted, it will fallback to the default settings. Its options are:
-
channel
: An interpolatedString
specifying the name of the channel. -
event
: An interpolatedString
specifying the name of the event.
Note: You will need a Pusher account, and to have set your API credentials in the initializer for this to work properly.
Optional as a Hash
.
This specifies a strategy by which the notification can be updated and marked as unread instead of recreated. Think of a messaging system—you probably don't want a new notification every time a message is sent, you may rather just update one notification between a sender and a recipient regarding a specific message. Its options are:
-
strategy
: This is the strategy by which we find and update messages. Right now, only:sender
is supported.:sender
will look for a notification sent to the same recipient with a trigger of that type. -
scope
: As aSymbol
representing a method on the trigger, it provides an option to narrow the scope of the strategy.
For example, say you want to update (instead of create) notifications between a sender and recipient regarding messages within a chat. Your settings may look like this, assuming Message
is the trigger.
:update => { :strategy => :sender, :scope => :chat }
Here's a bulky example using many of the options:
class Message < ActiveRecord::Base
notify_on(
:state_changed?,
:if => :active?,
:unless => :to_admin?,
:to => :user,
:from => :author,
:message => '{author_email} sent you a message.',
:link => 'message_path(:self)',
:email => {
:from => '{author.email}',
:template => 'new_message',
:attachments => { :pdf_name => :pdf_file }
},
:pusher => {
:channel => 'presence-{:env}-message-{id}',
:event => :new_message
}
)
def pdf_name
'my_file.pdf'
end
def pdf_file
open('http://loremflickr.com/200/200')
end
private
def to_admin?
user.admin?
end
end
Suppose we have a Message
object as message
, then its notification ...
- Would not be created unless
message.active?
istrue
andto_admin?
isfalse
- Gets sent to
message.user
- Comes from
message.author
- Has a description of
"#{author.email} has sent you a message."
- Would resolve to a path of
message_path(message)
- Sends an email from
message.author.email
using the template inapp/views/notifications/new_message.html.erb
- Sends a Pusher event named
"new_message"
to channel"presence-#{Rails.env.to_s}-message-#{message.id}"