Module: ActivityNotification::NotificationApi

Extended by:
ActiveSupport::Concern
Included in:
Notification
Defined in:
lib/activity_notification/apis/notification_api.rb

Overview

Defines API for notification included in Notification model.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.available_options ⇒ Array<Notificaion>

Returns available options for kinds of notify methods.

Returns:

  • (Array<Notificaion>) —

    Available options for kinds of notify methods



168
169
170
# File 'lib/activity_notification/apis/notification_api.rb', line 168

def available_options
  [:key, :group, :parameters, :notifier, :send_email, :send_later].freeze
end

.generate_notification(target, notifiable, options = {}) ⇒ Object

Generates a notification

Parameters:

  • target (Object) —

    Target to send notification

  • notifiable (Object) —

    Notifiable instance

  • options (Hash) (defaults to: {}) —

    Options for notification

Options Hash (options):

  • :key (String) — default: notifiable.default_notification_key —

    Key of the notification

  • :group (Object) — default: nil —

    Group unit of the notifications

  • :notifier (Object) — default: nil —

    Notifier of the notifications

  • :parameters (Hash) — default: {} —

    Additional parameters of the notifications



110
111
112
113
114
115
116
# File 'lib/activity_notification/apis/notification_api.rb', line 110

def generate_notification(target, notifiable, options = {})
  key = options[:key] || notifiable.default_notification_key
  if target.subscribes_to_notification?(key)
    # Store notification
    store_notification(target, notifiable, key, options)
  end
end

.group_member_exists?(notifications) ⇒ Boolean

Returns if group member of the notifications exists. This method is designed to be called from controllers or views to avoid N+1.

Parameters:

  • notifications (Array<Notificaion>, ActiveRecord_AssociationRelation<Notificaion>) —

    Array or database query of the notifications to test member exists

Returns:

  • (Boolean) —

    If group member of the notifications exists



140
141
142
# File 'lib/activity_notification/apis/notification_api.rb', line 140

def group_member_exists?(notifications)
  notifications.present? && where(group_owner_id: notifications.map(&:id)).exists?
end

.notify(target_type, notifiable, options = {}) ⇒ Array<Notificaion>

Generates notifications to configured targets with notifiable model.

Examples:

Use with target_type as Symbol

ActivityNotification::Notification.notify :users, @comment

Use with target_type as String

ActivityNotification::Notification.notify 'User', @comment

Use with target_type as Class

ActivityNotification::Notification.notify User, @comment

Use with options

ActivityNotification::Notification.notify :users, @comment, key: 'custom.comment', group: @comment.article
ActivityNotification::Notification.notify :users, @comment, parameters: { reply_to: @comment.reply_to }, send_later: false

Parameters:

  • target_type (Symbol, String, Class) —

    Type of target

  • notifiable (Object) —

    Notifiable instance

  • options (Hash) (defaults to: {}) —

    Options for notifications

Options Hash (options):

  • :key (String) — default: notifiable.default_notification_key —

    Key of the notification

  • :group (Object) — default: nil —

    Group unit of the notifications

  • :group_expiry_delay (ActiveSupport::Duration) — default: nil —

    Expiry period of a notification group

  • :notifier (Object) — default: nil —

    Notifier of the notifications

  • :parameters (Hash) — default: {} —

    Additional parameters of the notifications

  • :send_email (Boolean) — default: true —

    Whether it sends notification email

  • :send_later (Boolean) — default: true —

    Whether it sends notification email asynchronously

  • :publish_optional_targets (Boolean) — default: true —

    Whether it publishes notification to optional targets

  • :optional_targets (Hash<String, Hash>) — default: {} —

    Options for optional targets, keys are optional target name (:amazon_sns or :slack etc) and values are options

Returns:

  • (Array<Notificaion>) —

    Array of generated notifications



37
38
39
40
41
42
# File 'lib/activity_notification/apis/notification_api.rb', line 37

def notify(target_type, notifiable, options = {})
  targets = notifiable.notification_targets(target_type, options[:key])
  unless targets.blank?
    notify_all(targets, notifiable, options)
  end
end

.notify_all(targets, notifiable, options = {}) ⇒ Array<Notificaion>

Generates notifications to specified targets.

Examples:

Notify to all users

ActivityNotification::Notification.notify_all User.all, @comment

Parameters:

  • targets (Array<Object>) —

    Targets to send notifications

  • notifiable (Object) —

    Notifiable instance

  • options (Hash) (defaults to: {}) —

    Options for notifications

Options Hash (options):

  • :key (String) — default: notifiable.default_notification_key —

    Key of the notification

  • :group (Object) — default: nil —

    Group unit of the notifications

  • :group_expiry_delay (ActiveSupport::Duration) — default: nil —

    Expiry period of a notification group

  • :notifier (Object) — default: nil —

    Notifier of the notifications

  • :parameters (Hash) — default: {} —

    Additional parameters of the notifications

  • :send_email (Boolean) — default: true —

    Whether it sends notification email

  • :send_later (Boolean) — default: true —

    Whether it sends notification email asynchronously

  • :publish_optional_targets (Boolean) — default: true —

    Whether it publishes notification to optional targets

  • :optional_targets (Hash<String, Hash>) — default: {} —

    Options for optional targets, keys are optional target name (:amazon_sns or :slack etc) and values are options

Returns:

  • (Array<Notificaion>) —

    Array of generated notifications



62
63
64
# File 'lib/activity_notification/apis/notification_api.rb', line 62

def notify_all(targets, notifiable, options = {})
  targets.map { |target| target.notify_to(notifiable, options) }
end

.notify_to(target, notifiable, options = {}) ⇒ Notification

Generates notifications to one target.

Examples:

Notify to one user

ActivityNotification::Notification.notify_to @comment.auther, @comment

Parameters:

  • target (Object) —

    Target to send notifications

  • notifiable (Object) —

    Notifiable instance

  • options (Hash) (defaults to: {}) —

    Options for notifications

Options Hash (options):

  • :key (String) — default: notifiable.default_notification_key —

    Key of the notification

  • :group (Object) — default: nil —

    Group unit of the notifications

  • :group_expiry_delay (ActiveSupport::Duration) — default: nil —

    Expiry period of a notification group

  • :notifier (Object) — default: nil —

    Notifier of the notifications

  • :parameters (Hash) — default: {} —

    Additional parameters of the notifications

  • :send_email (Boolean) — default: true —

    Whether it sends notification email

  • :send_later (Boolean) — default: true —

    Whether it sends notification email asynchronously

  • :publish_optional_targets (Boolean) — default: true —

    Whether it publishes notification to optional targets

  • :optional_targets (Hash<String, Hash>) — default: {} —

    Options for optional targets, keys are optional target name (:amazon_sns or :slack etc) and values are options

Returns:



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/activity_notification/apis/notification_api.rb', line 84

def notify_to(target, notifiable, options = {})
  send_email            = options.has_key?(:send_email)                  ? options[:send_email]            : true
  send_later            = options.has_key?(:send_later)                  ? options[:send_later]            : true
  publish_optional_targets = options.has_key?(:publish_optional_targets) ? options[:publish_optional_targets] : true
  # Generate notification
  notification = generate_notification(target, notifiable, options)
  # Send notification email
  if notification.present? && send_email
    notification.send_notification_email({ send_later: send_later })
  end
  # Publish to optional targets
  if notification.present? && publish_optional_targets
    notification.publish_to_optional_targets(options[:optional_targets] || {})
  end
  # Return generated notification
  notification
end

.open_all_of(target, options = {}) ⇒ Integer

TODO:

Add filter option

Opens all notifications of the target.

Parameters:

  • target (Object) —

    Target of the notifications to open

  • options (Hash) (defaults to: {}) —

    Options for opening notifications

Options Hash (options):

  • :opened_at (DateTime) — default: Time.current —

    Time to set to opened_at of the notification record

  • :filtered_by_type (String) — default: nil —

    Notifiable type for filter

  • :filtered_by_group (Object) — default: nil —

    Group instance for filter

  • :filtered_by_group_type (String) — default: nil —

    Group type for filter, valid with :filtered_by_group_id

  • :filtered_by_group_id (String) — default: nil —

    Group instance id for filter, valid with :filtered_by_group_type

  • :filtered_by_key (String) — default: nil —

    Key of the notification for filter

Returns:

  • (Integer) —

    Number of opened notification records



130
131
132
133
# File 'lib/activity_notification/apis/notification_api.rb', line 130

def open_all_of(target, options = {})
  opened_at = options[:opened_at] || Time.current
  target.notifications.unopened_only.filtered_by_options(options).update_all(opened_at: opened_at)
end

.send_batch_notification_email(target, notifications, options = {}) ⇒ Mail::Message, ActionMailer::DeliveryJob|NilClass

Sends batch notification email to the target.

Parameters:

  • target (Object) —

    Target of batch notification email

  • notifications (Array<Notification>) —

    Target notifications to send batch notification email

  • options (Hash) (defaults to: {}) —

    Options for notification email

Options Hash (options):

  • :send_later (Boolean) — default: false —

    If it sends notification email asynchronously

  • :fallback (String, Symbol) — default: :batch_default —

    Fallback template to use when MissingTemplate is raised

  • :batch_key (String) — default: nil —

    Key of the batch notification email, a key of the first notification will be used if not specified

Returns:

  • (Mail::Message, ActionMailer::DeliveryJob|NilClass) —

    Email message or its delivery job, return NilClass for wrong target



153
154
155
156
157
158
159
160
161
162
163
# File 'lib/activity_notification/apis/notification_api.rb', line 153

def send_batch_notification_email(target, notifications, options = {})
  notifications.blank? and return
  batch_key = options[:batch_key] || notifications.first.key
  if target.batch_notification_email_allowed?(batch_key) &&
     target.subscribes_to_notification_email?(batch_key)
    send_later = options.has_key?(:send_later) ? options[:send_later] : true
    send_later ?
      Mailer.send_batch_notification_email(target, notifications, batch_key, options).deliver_later :
      Mailer.send_batch_notification_email(target, notifications, batch_key, options).deliver_now
  end
end

Instance Method Details

#email_subscribed? ⇒ Boolean

Returns if the target subscribes this notification email.

Returns:

  • (Boolean) —

    If the target subscribes the notification



369
370
371
# File 'lib/activity_notification/apis/notification_api.rb', line 369

def email_subscribed?
  target.subscribes_to_notification_email?(key)
end

#group_member? ⇒ Boolean

Returns if the notification is group member belonging to owner.

Returns:

  • (Boolean) —

    If the notification is group member



268
269
270
# File 'lib/activity_notification/apis/notification_api.rb', line 268

def group_member?
  group_owner_id.present?
end

#group_member_count(limit = ActivityNotification.config.opened_index_limit) ⇒ Integer

Returns count of group members of the notification. This method is designed to cache group by query result to avoid N+1 call.

Parameters:

  • limit (Integer) (defaults to: ActivityNotification.config.opened_index_limit) —

    Limit to query for opened notifications

Returns:

  • (Integer) —

    Count of group members of the notification



297
298
299
# File 'lib/activity_notification/apis/notification_api.rb', line 297

def group_member_count(limit = ActivityNotification.config.opened_index_limit)
  meta_group_member_count(:opened_group_member_count, :unopened_group_member_count, limit)
end

#group_member_exists?(limit = ActivityNotification.config.opened_index_limit) ⇒ Boolean

Returns if group member of the notification exists. This method is designed to cache group by query result to avoid N+1 call.

Parameters:

  • limit (Integer) (defaults to: ActivityNotification.config.opened_index_limit) —

    Limit to query for opened notifications

Returns:

  • (Boolean) —

    If group member of the notification exists



277
278
279
# File 'lib/activity_notification/apis/notification_api.rb', line 277

def group_member_exists?(limit = ActivityNotification.config.opened_index_limit)
  group_member_count(limit) > 0
end

#group_member_notifier_count(limit = ActivityNotification.config.opened_index_limit) ⇒ Integer

Returns count of group member notifiers of the notification not including group owner notifier. It always returns 0 if group owner notifier is blank. It counts only the member notifier of the same type with group owner notifier. This method is designed to cache group by query result to avoid N+1 call.

Parameters:

  • limit (Integer) (defaults to: ActivityNotification.config.opened_index_limit) —

    Limit to query for opened notifications

Returns:

  • (Integer) —

    Count of group member notifiers of the notification



317
318
319
# File 'lib/activity_notification/apis/notification_api.rb', line 317

def group_member_notifier_count(limit = ActivityNotification.config.opened_index_limit)
  meta_group_member_count(:opened_group_member_notifier_count, :unopened_group_member_notifier_count, limit)
end

#group_member_notifier_exists?(limit = ActivityNotification.config.opened_index_limit) ⇒ Boolean

Returns if group member notifier except group owner notifier exists. It always returns false if group owner notifier is blank. It counts only the member notifier of the same type with group owner notifier. This method is designed to cache group by query result to avoid N+1 call.

Parameters:

  • limit (Integer) (defaults to: ActivityNotification.config.opened_index_limit) —

    Limit to query for opened notifications

Returns:

  • (Boolean) —

    If group member of the notification exists



288
289
290
# File 'lib/activity_notification/apis/notification_api.rb', line 288

def group_member_notifier_exists?(limit = ActivityNotification.config.opened_index_limit)
  group_member_notifier_count(limit) > 0
end

#group_notification_count(limit = ActivityNotification.config.opened_index_limit) ⇒ Integer

Returns count of group notifications including owner and members. This method is designed to cache group by query result to avoid N+1 call.

Parameters:

  • limit (Integer) (defaults to: ActivityNotification.config.opened_index_limit) —

    Limit to query for opened notifications

Returns:

  • (Integer) —

    Count of group notifications including owner and members



306
307
308
# File 'lib/activity_notification/apis/notification_api.rb', line 306

def group_notification_count(limit = ActivityNotification.config.opened_index_limit)
  group_member_count(limit) + 1
end

#group_notifier_count(limit = ActivityNotification.config.opened_index_limit) ⇒ Integer

Returns count of group member notifiers including group owner notifier. It always returns 0 if group owner notifier is blank. This method is designed to cache group by query result to avoid N+1 call.

Parameters:

  • limit (Integer) (defaults to: ActivityNotification.config.opened_index_limit) —

    Limit to query for opened notifications

Returns:

  • (Integer) —

    Count of group notifications including owner and members



327
328
329
330
# File 'lib/activity_notification/apis/notification_api.rb', line 327

def group_notifier_count(limit = ActivityNotification.config.opened_index_limit)
  notification = group_member? ? group_owner : self
  notification.notifier.present? ? group_member_notifier_count(limit) + 1 : 0
end

#group_owner? ⇒ Boolean

Returns if the notification is group owner.

Returns:

  • (Boolean) —

    If the notification is group owner



261
262
263
# File 'lib/activity_notification/apis/notification_api.rb', line 261

def group_owner?
  group_owner_id.blank?
end

#latest_group_member ⇒ Notificaion

Returns the latest group member notification instance of this notification. If this group owner has no group members, group owner instance self will be returned.

Returns:

  • (Notificaion) —

    Notification instance of the latest group member notification



336
337
338
339
# File 'lib/activity_notification/apis/notification_api.rb', line 336

def latest_group_member
  notification = group_member? ? group_owner : self
  notification.group_member_exists? ? notification.group_members.latest : self
end

#notifiable_path ⇒ String

Returns notifiable_path to move after opening notification with notifiable.notifiable_path.

Returns:

  • (String) —

    Notifiable path URL to move after opening notification



356
357
358
359
# File 'lib/activity_notification/apis/notification_api.rb', line 356

def notifiable_path
  notifiable.present? or raise ActiveRecord::RecordNotFound.new("Couldn't find notifiable #{notifiable_type}")
  notifiable.notifiable_path(target_type, key)
end

#open!(options = {}) ⇒ Integer

Opens the notification.

Parameters:

  • options (Hash) (defaults to: {}) —

    Options for opening notifications

Options Hash (options):

  • :opened_at (DateTime) — default: Time.current —

    Time to set to opened_at of the notification record

  • :with_members (Boolean) — default: true —

    If it opens notifications including group members

Returns:

  • (Integer) —

    Number of opened notification records



237
238
239
240
241
242
# File 'lib/activity_notification/apis/notification_api.rb', line 237

def open!(options = {})
  opened_at = options[:opened_at] || Time.current
  with_members = options.has_key?(:with_members) ? options[:with_members] : true
  update(opened_at: opened_at)
  with_members ? group_members.update_all(opened_at: opened_at) + 1 : 1
end

#opened? ⇒ Boolean

Returns if the notification is opened.

Returns:

  • (Boolean) —

    If the notification is opened



254
255
256
# File 'lib/activity_notification/apis/notification_api.rb', line 254

def opened?
  opened_at.present?
end

#optional_target_names ⇒ Array<Symbol>

Returns optional_target names of the notification from configured field or overriden method.

Returns:

  • (Array<Symbol>) —

    Array of optional target names



388
389
390
# File 'lib/activity_notification/apis/notification_api.rb', line 388

def optional_target_names
  notifiable.optional_target_names(target.to_resources_name, key)
end

#optional_target_subscribed?(optional_target_name) ⇒ Boolean

Returns if the target subscribes this notification email.

Parameters:

  • optional_target_name (String, Symbol) —

    Class name of the optional target implementation (e.g. :amazon_sns, :slack)

Returns:

  • (Boolean) —

    If the target subscribes the specified optional target of the notification



376
377
378
# File 'lib/activity_notification/apis/notification_api.rb', line 376

def optional_target_subscribed?(optional_target_name)
  target.subscribes_to_optional_target?(key, optional_target_name)
end

#optional_targets ⇒ Array<ActivityNotification::OptionalTarget::Base>

Returns optional_targets of the notification from configured field or overriden method.

Returns:



382
383
384
# File 'lib/activity_notification/apis/notification_api.rb', line 382

def optional_targets
  notifiable.optional_targets(target.to_resources_name, key)
end

#publish_to_optional_targets(options = {}) ⇒ Hash

Publishes notification to the optional targets.

Parameters:

  • options (Hash) (defaults to: {}) —

    Options for optional targets

Returns:

  • (Hash) —

    Result of publishing to optional target



219
220
221
222
223
224
225
226
227
228
229
# File 'lib/activity_notification/apis/notification_api.rb', line 219

def publish_to_optional_targets(options = {})
  notifiable.optional_targets(target.to_resources_name, key).map { |optional_target|
    optional_target_name = optional_target.to_optional_target_name
    if optional_target_subscribed?(optional_target_name)
      optional_target.notify(self, options[optional_target_name] || {})
      [optional_target_name, true]
    else
      [optional_target_name, false]
    end
  }.to_h
end

#remove_from_group ⇒ Notificaion

Remove from notification group and make a new group owner.

Returns:

  • (Notificaion) —

    New group owner instance of the notification group



344
345
346
347
348
349
350
351
# File 'lib/activity_notification/apis/notification_api.rb', line 344

def remove_from_group
  new_group_owner = group_members.earliest
  if new_group_owner.present?
    new_group_owner.update(group_owner_id: nil)
    group_members.update_all(group_owner_id: new_group_owner)
  end
  new_group_owner
end

#send_notification_email(options = {}) ⇒ Mail::Message, ActionMailer::DeliveryJob

Sends notification email to the target.

Parameters:

  • options (Hash) (defaults to: {}) —

    Options for notification email

Options Hash (options):

  • :send_later (Boolean) —

    If it sends notification email asynchronously

  • :fallback (String, Symbol) — default: :default —

    Fallback template to use when MissingTemplate is raised

Returns:

  • (Mail::Message, ActionMailer::DeliveryJob) —

    Email message or its delivery job



204
205
206
207
208
209
210
211
212
213
# File 'lib/activity_notification/apis/notification_api.rb', line 204

def send_notification_email(options = {})
  if target.notification_email_allowed?(notifiable, key) &&
     notifiable.notification_email_allowed?(target, key) &&
     email_subscribed?
    send_later = options.has_key?(:send_later) ? options[:send_later] : true
    send_later ?
      Mailer.send_notification_email(self, options).deliver_later :
      Mailer.send_notification_email(self, options).deliver_now
  end
end

#subscribed? ⇒ Boolean

Returns if the target subscribes this notification.

Returns:

  • (Boolean) —

    If the target subscribes the notification



363
364
365
# File 'lib/activity_notification/apis/notification_api.rb', line 363

def subscribed?
  target.subscribes_to_notification?(key)
end

#unopened? ⇒ Boolean

Returns if the notification is unopened.

Returns:

  • (Boolean) —

    If the notification is unopened



247
248
249
# File 'lib/activity_notification/apis/notification_api.rb', line 247

def unopened?
  !opened?
end