Class: NotifyUser::BaseNotification

Inherits:
ActiveRecord::Base
  • Object
show all
Defined in:
app/models/notify_user/base_notification.rb

Constant Summary collapse

@@channels =
{
  action_mailer: {},
}
@@views =
{
  mobile_sdk: {
    template_path: Proc.new {|n| "notify_user/#{n.class.name.underscore}/mobile_sdk/notification" }
  }
}
@@aggregate_per =
1.minute

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.channel(name, options = {}) ⇒ Object

Configure a channel



106
107
108
# File 'app/models/notify_user/base_notification.rb', line 106

def self.channel(name, options={})
  channels[name] = options
end

.deliver_channels(notification_id) ⇒ Object

Deliver a single notification across each channel.



148
149
150
151
152
153
154
155
156
# File 'app/models/notify_user/base_notification.rb', line 148

def self.deliver_channels(notification_id)
  notification = self.where(id: notification_id).first
  return unless notification

  self.channels.each do |channel_name, options|
    channel = (channel_name.to_s + "_channel").camelize.constantize
    channel.deliver(notification, options)
  end
end

.deliver_channels_aggregated(notifications) ⇒ Object

Deliver multiple notifications across each channel as an aggregate message.



159
160
161
162
163
164
# File 'app/models/notify_user/base_notification.rb', line 159

def self.deliver_channels_aggregated(notifications)
  self.channels.each do |channel_name, options|
    channel = (channel_name.to_s + "_channel").camelize.constantize
    channel.deliver_aggregated(notifications, options)
  end
end

.for_target(target) ⇒ Object

Sending



117
118
119
120
# File 'app/models/notify_user/base_notification.rb', line 117

def self.for_target(target)
  where(target_id: target.id)
  .where(target_type: target.class.name)
end

.notify_aggregated(notification_id) ⇒ Object



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'app/models/notify_user/base_notification.rb', line 166

def self.notify_aggregated(notification_id)
  notification = self.find(notification_id) # Raise an exception if not found.

  # Find any pending notifications with the same type and target, which can all be sent in one message.
  notifications = self.pending_aggregation_with(notification)
  
  notifications.map(&:mark_as_sent)
  notifications.map(&:save)

  return if notifications.empty?

  if notifications.length == 1
    # Despite waiting for more to aggregate, we only got one in the end.
    self.deliver_channels(notifications.first.id)
  else
    # We got several notifications while waiting, send them aggregated.
    self.deliver_channels_aggregated(notifications)
  end
end

.pending_aggregation_with(notification) ⇒ Object



122
123
124
125
126
# File 'app/models/notify_user/base_notification.rb', line 122

def self.pending_aggregation_with(notification)
  where(type: notification.type)
  .for_target(notification.target)
  .where(state: :pending)
end

Instance Method Details

#aggregate_perObject

Aggregation



112
# File 'app/models/notify_user/base_notification.rb', line 112

mattr_accessor :aggregate_per

#aggregation_pending?Boolean

Returns:

  • (Boolean)


128
129
130
131
132
# File 'app/models/notify_user/base_notification.rb', line 128

def aggregation_pending?
  # A notification of the same type, that would have an aggregation job associated with it,
  # already exists.
  return (self.class.pending_aggregation_with(self).where('id != ?', id).count > 0)
end

#channelsObject

Channels



91
# File 'app/models/notify_user/base_notification.rb', line 91

mattr_accessor :channels

#deliverObject



134
135
136
137
138
139
# File 'app/models/notify_user/base_notification.rb', line 134

def deliver
  self.mark_as_sent
  self.save

  self.class.delay.deliver_channels(self.id)
end

#deliver!Object



141
142
143
144
145
# File 'app/models/notify_user/base_notification.rb', line 141

def deliver!
  self.mark_as_sent
  self.save
  self.class.deliver_channels(self.id)
end

#notifyObject

Send any Emails/SMS/APNS



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'app/models/notify_user/base_notification.rb', line 69

def notify

  save!

  if self.class.aggregate_per

    # Schedule to send later if there aren't already any scheduled.
    # Otherwise ignore, as the already-scheduled aggregate job will pick this one up when it runs.
    if not aggregation_pending?

      # Send in X minutes, along with any others created in the intervening times.
      self.class.delay_for(self.class.aggregate_per).notify_aggregated(self.id)
    end
  else
    # No aggregation, send immediately.
    self.deliver
  end

end

#notify!Object



61
62
63
64
65
66
# File 'app/models/notify_user/base_notification.rb', line 61

def notify!
  save!

  # Bang version of 'notify' ignores aggregation
  self.deliver!
end

#to(user) ⇒ Object

Public Interface



51
52
53
54
# File 'app/models/notify_user/base_notification.rb', line 51

def to(user)
  self.target = user
  self
end

#with(*args) ⇒ Object



56
57
58
59
# File 'app/models/notify_user/base_notification.rb', line 56

def with(*args)
  self.params = args.reduce({}, :update)
  self
end