Skip to content
Sean C Davis edited this page Oct 26, 2016 · 3 revisions

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.

Action

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.

Custom Conditionals

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

Options

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.

to

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.

from

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.

message

Required as an interpolated String.

The message is meant to be a brief description of the notification.

link

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.

if/unless

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.)

email

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 uses NotifyOn.configuration.default_email.
  • template: The name of the email template to render. It defaults to notify. See Override Default Email Message for more information.
  • unless: A Symbol representing a conditional method (on the trigger) returning a boolean. If this method returns true, the email will not be sent, assuming email is enabled.
  • attachments: A Hash 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: A Boolean that, if set to true, will attempt to save the email's Message-ID header to a message_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.

pusher

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:

Note: You will need a Pusher account, and to have set your API credentials in the initializer for this to work properly.

update

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 a Symbol 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 }

Examples

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? is true and to_admin? is false
  • 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 in app/views/notifications/new_message.html.erb
  • Sends a Pusher event named "new_message" to channel "presence-#{Rails.env.to_s}-message-#{message.id}"