module SimpleNotifications::Base

Public Instance Methods

acts_as_notifier(options = {}) click to toggle source

notify sender: :product_class,

receivers: :variants,
action: [:follow, :update, :create, :destroy]
# File lib/simple_notifications/base.rb, line 8
def acts_as_notifier(options = {})
  Base.options = options
  raise 'SimpleNotifications::ActionsNotAvailable' if Base.options[:actions].nil? || Base.options[:actions].empty?

  # Default Assumptions
  Base.options[:sender] ||= :user # Default Assumption: [:user] association is available.
  Base.options[:entity_class] = self

  # Filter system defined callback actions
  # After this
  # Base.options[:callbacks] -> will have all system defined actions only like (create/update/destroy)
  # Base.options[:actions]   -> will have user defined actions only.
  Base.options[:callbacks] = []
  %i[create update destroy].each {|method| Base.options[:callbacks] << Base.options[:actions].delete(method)}
  Base.options[:callbacks].compact!

  open_sender_class
  open_receiver_class
  open_notified_class

  Base.active = true
end
create_notification() click to toggle source
# File lib/simple_notifications/base.rb, line 80
def create_notification
  notify(sender: get_obj(Base.options[:sender]),
         receivers: get_obj(Base.options[:receivers]),
         action: 'create',
         message: default_message(self, get_obj(Base.options[:sender]), 'created'))
end
default_message(entity, sender, action) click to toggle source
# File lib/simple_notifications/base.rb, line 193
def default_message(entity, sender, action)
  @message ||
    (method(Base.options[:notify_message]).call if !!Base.options[:notify_message]) ||
    "#{get_obj(sender).class.name} #{action} #{entity.class.name} #{entity.name}"
end
destroy_notification() click to toggle source
# File lib/simple_notifications/base.rb, line 94
def destroy_notification
  notify(sender: get_obj(Base.options[:sender]),
         receivers: get_obj(Base.options[:receivers]),
         action: 'destroy',
         message: default_message(self, get_obj(Base.options[:sender]), 'destroyed'))
end
flush_notifications() click to toggle source
# File lib/simple_notifications/base.rb, line 150
def flush_notifications
  notifications.destroy_all
end
get_obj(sender_or_receivers) click to toggle source
# File lib/simple_notifications/base.rb, line 201
def get_obj(sender_or_receivers)
  sender_or_receivers.kind_of?(Symbol) ? send(sender_or_receivers) : sender_or_receivers
end
mark_read(notificants = nil) click to toggle source

Mark notifications in read mode. If notificants are provided then only those respective notifications will be marked read. Else all will be marked as read.

# File lib/simple_notifications/base.rb, line 182
def mark_read(notificants = nil)
  (notificants ? unread_deliveries.where(receiver: notificants) : unread_deliveries).update_all(is_read: true)
end
mark_unread(notificants = nil) click to toggle source

Mark notifications in unread mode. If notificants are provided then only those respective notifications will be marked unread. Else all will be marked as unread.

# File lib/simple_notifications/base.rb, line 189
def mark_unread(notificants = nil)
  (notificants ? read_deliveries.where(receiver: notificants) : read_deliveries).update_all(is_read: false)
end
notificants() click to toggle source
# File lib/simple_notifications/base.rb, line 159
def notificants
  SimpleNotifications::Record.includes(deliveries: :receiver)
    .collect(&:deliveries).flatten
    .collect(&:receiver)
end
notifications_active?() click to toggle source

Getter to check if model is enabled with notifications

# File lib/simple_notifications/base.rb, line 32
def notifications_active?
  !!Base.active
end
notified?() click to toggle source

Check if notifications has already been delivered.

# File lib/simple_notifications/base.rb, line 155
def notified?
  !notifications.blank?
end
notify(options = {}) click to toggle source

————————————————– # Example post.notify(sender: :author, receivers: :followers, message: 'My Custom logic message') post.create(content: '', notify: false) -> It does not create the notification.

# File lib/simple_notifications/base.rb, line 134
def notify(options = {})
  options[:sender] ||= Base.options[:sender]
  options[:receivers] ||= Base.options[:receivers]
  if notify_flag.nil? || (!notify_flag.nil? && !!notify_flag)
    raise 'SimpleNotification::SenderReceiverError' unless Base.options[:sender] && Base.options[:receivers]

    @message = options[:message] if options[:message]
    notification = notifications.build(entity: self,
                                       sender: get_obj(options[:sender]),
                                       action: options[:action] || '',
                                       message: default_message(self, get_obj(options[:sender]), 'notified'))
    [get_obj(options[:receivers])].flatten.each {|receiver| notification.deliveries.build(receiver: receiver)}
    notification.save
  end
end
open_notified_class() click to toggle source

Opening the class on which the notify functionality is applied.

Calls superclass method
# File lib/simple_notifications/base.rb, line 56
def open_notified_class
  class_eval do
    prepend NotificationActions # For adding all user defined methods at the last level of present class
    attr_accessor :message, :notify_flag

    # -------------------------------------------------- #
    # Define association for the notified model
    # -------------------------------------------------- #
    has_many :notifications, class_name: 'SimpleNotifications::Record', as: :entity
    has_many :notifiers, through: :notifications, source: :sender,
             source_type: sender_class(Base.options[:sender]).to_s
    has_many :read_deliveries, through: :notifications, source: :read_deliveries
    has_many :unread_deliveries, through: :notifications, source: :unread_deliveries

    # -------------------------------------------------- #
    # For defining the System defined callbacks
    # -------------------------------------------------- #

    # Callbacks
    # after_create_commit :create_notification
    Base.options[:callbacks].each do |callback|
      send("after_#{callback}_commit", "#{callback}_notification".to_sym)
    end

    def create_notification
      notify(sender: get_obj(Base.options[:sender]),
             receivers: get_obj(Base.options[:receivers]),
             action: 'create',
             message: default_message(self, get_obj(Base.options[:sender]), 'created'))
    end

    def update_notification
      notify(sender: get_obj(Base.options[:sender]),
             receivers: get_obj(Base.options[:receivers]),
             action: 'update',
             message: default_message(self, get_obj(Base.options[:sender]), 'updated'))
    end

    def destroy_notification
      notify(sender: get_obj(Base.options[:sender]),
             receivers: get_obj(Base.options[:receivers]),
             action: 'destroy',
             message: default_message(self, get_obj(Base.options[:sender]), 'destroyed'))
    end

    # -------------------------------------------------- #
    # For defining the callbacks for user defined actions
    # -------------------------------------------------- #
    NotificationActions.module_eval do
      Base.options[:actions].each do |action|
        define_method(action) do
          run_callbacks action do
            super()
          end
        end

        define_method("before_#{action}".to_sym) do
        end

        define_method("after_#{action}".to_sym) do
          notify(sender: Base.options[:sender],
                 receivers: Base.options[:receivers],
                 action: action,
                 message: default_message(self, Base.options[:sender], action.to_s))
        end
      end
    end

    Base.options[:actions].each do |action|
      define_model_callbacks action
      send("before_#{action}", "before_#{action}".to_sym)
      send("after_#{action}", "after_#{action}".to_sym)
    end

    # -------------------------------------------------- #
    # Example
    # post.notify(sender: :author, receivers: :followers, message: 'My Custom logic message')
    # post.create(content: '', notify: false) -> It does not create the notification.
    def notify(options = {})
      options[:sender] ||= Base.options[:sender]
      options[:receivers] ||= Base.options[:receivers]
      if notify_flag.nil? || (!notify_flag.nil? && !!notify_flag)
        raise 'SimpleNotification::SenderReceiverError' unless Base.options[:sender] && Base.options[:receivers]

        @message = options[:message] if options[:message]
        notification = notifications.build(entity: self,
                                           sender: get_obj(options[:sender]),
                                           action: options[:action] || '',
                                           message: default_message(self, get_obj(options[:sender]), 'notified'))
        [get_obj(options[:receivers])].flatten.each {|receiver| notification.deliveries.build(receiver: receiver)}
        notification.save
      end
    end

    def flush_notifications
      notifications.destroy_all
    end

    # Check if notifications has already been delivered.
    def notified?
      !notifications.blank?
    end

    def notificants
      SimpleNotifications::Record.includes(deliveries: :receiver)
        .collect(&:deliveries).flatten
        .collect(&:receiver)
    end

    def read_marked_notificants
      SimpleNotifications::Record.includes(deliveries: :receiver)
        .collect(&:deliveries).flatten
        .select(&:is_read)
        .collect(&:receiver)
    end

    def unread_marked_notificants
      SimpleNotifications::Record
        .includes(deliveries: :receiver)
        .collect(&:deliveries).flatten
        .reject {|record| record.is_read}.collect(&:receiver)
    end

    # Mark notifications in read mode.
    # If notificants are provided then only those respective notifications will be marked read.
    # Else all will be marked as read.
    def mark_read(notificants = nil)
      (notificants ? unread_deliveries.where(receiver: notificants) : unread_deliveries).update_all(is_read: true)
    end

    # Mark notifications in unread mode.
    # If notificants are provided then only those respective notifications will be marked unread.
    # Else all will be marked as unread.
    def mark_unread(notificants = nil)
      (notificants ? read_deliveries.where(receiver: notificants) : read_deliveries).update_all(is_read: false)
    end

    def default_message(entity, sender, action)
      @message ||
        (method(Base.options[:notify_message]).call if !!Base.options[:notify_message]) ||
        "#{get_obj(sender).class.name} #{action} #{entity.class.name} #{entity.name}"
    end

    private

    def get_obj(sender_or_receivers)
      sender_or_receivers.kind_of?(Symbol) ? send(sender_or_receivers) : sender_or_receivers
    end
  end
end
open_receiver_class() click to toggle source

Opening the classes which are defined as receivers.

# File lib/simple_notifications/base.rb, line 45
def open_receiver_class
  # Define association for receiver model
  [receivers_class(Base.options[:receivers])].flatten.each do |base|
    base.class_eval do
      has_many :deliveries, class_name: 'SimpleNotifications::Delivery', as: :receiver
      has_many :received_notifications, through: :deliveries, source: :simple_notification
    end
  end
end
open_sender_class() click to toggle source

Opening the class which is defined as sender.

# File lib/simple_notifications/base.rb, line 37
def open_sender_class
  # Define association for sender model
  sender_class(Base.options[:sender]).class_eval do
    has_many :sent_notifications, class_name: 'SimpleNotifications::Record', as: :sender
  end
end
read_marked_notificants() click to toggle source
# File lib/simple_notifications/base.rb, line 165
def read_marked_notificants
  SimpleNotifications::Record.includes(deliveries: :receiver)
    .collect(&:deliveries).flatten
    .select(&:is_read)
    .collect(&:receiver)
end
receivers_class(receivers) click to toggle source

Provides the classes of Receivers

# File lib/simple_notifications/base.rb, line 219
def receivers_class(receivers)
  if receivers.kind_of? Symbol
    reflections[receivers.to_s].klass
  else
    if receivers.kind_of? ActiveRecord::Base
      receivers.class
    elsif receivers.kind_of? ActiveRecord::Relation
      receivers.klass
    elsif receivers.kind_of? Array
      receivers.flatten.collect {|receiver| receivers_class(receiver)}
    else
      raise 'SimpleNotifications::ReceiverTypeError'
    end
  end
end
sender_class(sender) click to toggle source

Provides the class of Sender

# File lib/simple_notifications/base.rb, line 208
def sender_class(sender)
  if sender.kind_of? Symbol
    reflections[sender.to_s].klass
  elsif sender.kind_of? ActiveRecord::Base
    sender.class
  else
    raise 'SimpleNotifications::SenderTypeError'
  end
end
unread_marked_notificants() click to toggle source
# File lib/simple_notifications/base.rb, line 172
def unread_marked_notificants
  SimpleNotifications::Record
    .includes(deliveries: :receiver)
    .collect(&:deliveries).flatten
    .reject {|record| record.is_read}.collect(&:receiver)
end
update_notification() click to toggle source
# File lib/simple_notifications/base.rb, line 87
def update_notification
  notify(sender: get_obj(Base.options[:sender]),
         receivers: get_obj(Base.options[:receivers]),
         action: 'update',
         message: default_message(self, get_obj(Base.options[:sender]), 'updated'))
end