notify_user 0.0.1 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. checksums.yaml +7 -0
  2. data/app/assets/javascripts/notify_user/notification.js +7 -0
  3. data/app/assets/stylesheets/notify_user/notify_user.css +50 -0
  4. data/app/controllers/notify_user/base_notifications_controller.rb +144 -0
  5. data/app/controllers/notify_user/notifications_controller.rb +7 -32
  6. data/app/helpers/notify_user/application_helper.rb +9 -0
  7. data/app/mailers/notify_user/notification_mailer.rb +2 -0
  8. data/app/models/notify_user/apns.rb +37 -0
  9. data/app/models/notify_user/base_notification.rb +136 -32
  10. data/app/models/notify_user/unsubscribe.rb +55 -0
  11. data/app/models/notify_user/user_hash.rb +36 -0
  12. data/app/serializers/notify_user/notification_serializer.rb +2 -2
  13. data/app/views/notify_user/action_mailer/aggregate_notification.html.erb +2 -1
  14. data/app/views/notify_user/action_mailer/notification.html.erb +1 -1
  15. data/app/views/notify_user/base_notifications/index.html.erb +20 -0
  16. data/app/views/notify_user/base_notifications/unsubscribe.html.erb +19 -0
  17. data/config/routes.rb +8 -0
  18. data/lib/generators/notify_user/install/install_generator.rb +20 -3
  19. data/lib/generators/notify_user/install/templates/{migration.rb → create_notify_user_notifications.rb} +1 -1
  20. data/lib/generators/notify_user/install/templates/create_notify_user_unsubscribes.rb +10 -0
  21. data/lib/generators/notify_user/install/templates/create_notify_user_user_hashes.rb +12 -0
  22. data/lib/generators/notify_user/install/templates/initializer.rb +2 -0
  23. data/lib/generators/notify_user/install/templates/notifications_controller.rb +9 -0
  24. data/lib/generators/notify_user/json_update/USAGE +5 -0
  25. data/lib/generators/notify_user/json_update/json_update_generator.rb +36 -0
  26. data/lib/generators/notify_user/json_update/templates/add_json_column_to_notifications.rb +9 -0
  27. data/lib/generators/notify_user/json_update/templates/move_params_to_json.rb +8 -0
  28. data/lib/generators/notify_user/notification/notification_generator.rb +2 -0
  29. data/lib/generators/notify_user/notification/templates/email_layout_template.html.erb.erb +6 -0
  30. data/lib/generators/notify_user/notification/templates/notification.rb.erb +2 -1
  31. data/lib/notify_user.rb +4 -1
  32. data/lib/notify_user/channels/action_mailer/action_mailer_channel.rb +2 -1
  33. data/lib/notify_user/channels/apns/apns_channel.rb +17 -0
  34. data/lib/notify_user/engine.rb +2 -0
  35. data/lib/notify_user/railtie.rb +10 -0
  36. data/lib/notify_user/version.rb +1 -1
  37. data/lib/tasks/notify_user.rake +15 -0
  38. data/spec/controllers/notify_user/notifications_controller_spec.rb +89 -1
  39. data/spec/dummy/rails-4.0.2/Gemfile +2 -2
  40. data/spec/dummy/rails-4.0.2/app/controllers/notify_user/notifications_controller.rb +9 -0
  41. data/spec/dummy/rails-4.0.2/app/notifications/new_post_notification.rb +2 -1
  42. data/spec/dummy/rails-4.0.2/app/views/notify_user/layouts/action_mailer.html.erb +6 -0
  43. data/spec/dummy/rails-4.0.2/config/database.yml +42 -13
  44. data/spec/dummy/rails-4.0.2/config/database2.yml +57 -0
  45. data/spec/dummy/rails-4.0.2/config/initializers/notify_user.rb +2 -0
  46. data/spec/dummy/rails-4.0.2/config/initializers/secret_token.rb +1 -1
  47. data/spec/dummy/rails-4.0.2/db/migrate/{20140105070446_create_users.rb → 20140428015529_create_users.rb} +0 -0
  48. data/spec/dummy/rails-4.0.2/db/migrate/{20140105070448_create_notify_user_notifications.rb → 20140428015531189189694000_create_notify_user_notifications.rb} +1 -1
  49. data/spec/dummy/rails-4.0.2/db/migrate/20140428015531190190743000_create_notify_user_unsubscribes.rb +10 -0
  50. data/spec/dummy/rails-4.0.2/db/migrate/20140428015531191191953000_create_notify_user_user_hashes.rb +12 -0
  51. data/spec/dummy/rails-4.0.2/db/schema.rb +23 -2
  52. data/spec/dummy/rails-4.0.2/log/test.log +787 -1414
  53. data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/13195a56ea8581e42f709ea01ea4604f +0 -0
  54. data/{app/assets/stylesheets/notify_user/application.css → spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/13fe41fee1fe35b49d145bcc06610705} +0 -0
  55. data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/148f39f7dc2ea6cb194598111dbd4598 +0 -0
  56. data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/1d6bc1877ba2bbb89f393e10e8303d39 +0 -0
  57. data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  58. data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/311d2b645a860b78f79ff156f12092ce +0 -0
  59. data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  60. data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/39651f0f2ac78423732234ebf092c632 +0 -0
  61. data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/5c85b1b5ac27b699c5f800c4e7ec82fb +0 -0
  62. data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/68752c7ddc300bee3e9823db8befc306 +0 -0
  63. data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/6961013077b8573ed19d1e33abb8ebc5 +0 -0
  64. data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/7a316b3629b980c6d3a28924cb5fbbd8 +0 -0
  65. data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/8698d6fed0ef2f173a377160752b959f +0 -0
  66. data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/8bab520aad78da438df1c428288cf229 +0 -0
  67. data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  68. data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  69. data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  70. data/spec/dummy/rails-4.0.2/tmp/cache/assets/test/sprockets/fa138a16887e031c0ae1b4caccfb4c05 +0 -0
  71. data/spec/mailers/notify_user/notification_mailer_spec.rb +1 -0
  72. data/spec/models/notify_user/notification_spec.rb +122 -1
  73. data/spec/models/notify_user/unsubscribe_spec.rb +40 -0
  74. data/spec/models/notify_user/user_hash_spec.rb +35 -0
  75. data/spec/spec_helper.rb +5 -0
  76. data/spec/support/database.yml +21 -0
  77. data/spec/support/rails_template.rb +9 -0
  78. metadata +196 -65
  79. data/spec/dummy/rails-4.0.2/db/test.sqlite3 +0 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6ccbda4d4f6f0bd85a37c2e9295789c8c3c28844
4
+ data.tar.gz: f8f67249b41082e9af5dc4686bb3f85639360507
5
+ SHA512:
6
+ metadata.gz: b9258b901edd1eb111a33354aafc2aa668b7520587594fad58e03d5d887042836633cc620a8b49d167220ebb16cac1c18423c78d9d45d8fc9bbbf76d4d5eaf78
7
+ data.tar.gz: ae8fd4a46fde87ffe996adc8e42e63b667a5b0525ceb269205a76e437a17df21209ff5f7f8e59d1298f4eee57cec35738b0d3059b094aa80876808cf8712f42f
@@ -0,0 +1,7 @@
1
+ $( document ).ready(function() {
2
+ $('.message').click(function(){
3
+ item = $(this).parent().parent();
4
+ item.addClass('read');
5
+
6
+ });
7
+ });
@@ -0,0 +1,50 @@
1
+ .unread a{
2
+ font-weight: bold;
3
+ }
4
+ .read a{
5
+ font-weight: normal;
6
+ }
7
+ #notifications_list{
8
+ margin: 0 auto;
9
+ width: 100%;
10
+ width: 720px;
11
+ color: #000;
12
+ font-family: arial;
13
+ font-size: 14px;
14
+ text-align: right;
15
+ padding: 5px;
16
+ text-align: center;
17
+ }
18
+
19
+ #notifications_list .inner{
20
+ margin-top: 10px;
21
+ border: 1px solid #dedede;
22
+ text-align: left;
23
+
24
+ }
25
+ #notifications_list a{
26
+ color: #454545;
27
+ text-decoration: none;
28
+ }
29
+ #notifications_list .item:hover a{
30
+ text-decoration: underline;
31
+ }
32
+
33
+ #notifications_list .title{
34
+ text-align: left;
35
+ }
36
+
37
+ #notifications_list .item{
38
+ padding: 20px 10px;
39
+ border-bottom: 1px solid #dedede;
40
+ }
41
+ #notifications_list .item.read{
42
+ background: #eaeaea;
43
+ }
44
+ #notifications_list .item .time_ago{
45
+ font-size: 12px;
46
+ text-align: right;
47
+ }
48
+ #notifications_list .mark_as_read{
49
+ text-align: right;
50
+ }
@@ -0,0 +1,144 @@
1
+ class NotifyUser::BaseNotificationsController < ApplicationController
2
+
3
+ before_filter :authenticate!, :except => [:unauth_unsubscribe]
4
+
5
+ def index
6
+ @notifications = NotifyUser::BaseNotification.for_target(@user)
7
+ .order("created_at DESC")
8
+ .limit(30)
9
+ .page(params[:page]).per(params[:per_page])
10
+
11
+ respond_to do |format|
12
+ format.html
13
+ format.json {render :json => @notifications, meta: { pagination: { per_page: @notifications.limit_value, total_pages: @notifications.total_pages, total_objects: @notifications.total_count } }}
14
+ end
15
+ end
16
+
17
+ def mark_read
18
+ @notifications = NotifyUser::BaseNotification.for_target(@user).where('id IN (?)', params[:ids])
19
+ @notifications.update_all(state: :read)
20
+ render json: @notifications
21
+ end
22
+
23
+ def mark_all
24
+ @notifications = NotifyUser::BaseNotification.for_target(@user).where('state IN (?)', ["pending","sent"])
25
+ @notifications.update_all(state: :read)
26
+ redirect_to notify_user_notifications_path
27
+ end
28
+
29
+ def notifications_count
30
+ @notifications = NotifyUser::BaseNotification.for_target(@user).where('state IN (?)', ["sent"])
31
+ render json: {:count => @notifications.count}
32
+ end
33
+
34
+ #get
35
+ def read
36
+ @notification = NotifyUser::BaseNotification.for_target(@user).where('id = ?', params[:id]).first
37
+ @notification.mark_as_read
38
+ redirect_logic(@notification)
39
+ end
40
+
41
+ def redirect_logic(notification)
42
+ render :text => "redirect setup goes here"
43
+ end
44
+
45
+ def unsubscribe
46
+ if params[:type]
47
+ unsubscribe_from(params[:type])
48
+ redirect_to notify_user_notifications_unsubscribe_path
49
+ end
50
+ @unsubscribale_types = NotifyUser.unsubscribable_notifications
51
+ @unsubscribale_channels = NotifyUser::BaseNotification.channels
52
+ end
53
+
54
+ #endpoint for accessing subscriptions and their statuses
55
+ def subscriptions
56
+ update_subscriptions(params[:types]) if params[:types]
57
+ @types = build_notification_types
58
+ render :json => @types
59
+ end
60
+
61
+ def update_subscriptions(types)
62
+ types.each do |type|
63
+ unsubscribe = NotifyUser::Unsubscribe.has_unsubscribed_from(@user, type[:type])
64
+ if type[:status] == '0'
65
+ if unsubscribe.empty?
66
+ #if unsubscribe doesn't exist create it
67
+ unsubscribe = NotifyUser::Unsubscribe.create(target: @user, type: type[:type])
68
+ end
69
+ else
70
+ subscribe_to(type[:type])
71
+ end
72
+ end
73
+ end
74
+
75
+ def unauth_unsubscribe
76
+ if params[:token] && params[:type]
77
+ if NotifyUser::UserHash.confirm_hash(params[:token], params[:type])
78
+ user_hash = NotifyUser::UserHash.where(token: params[:token], type: params[:type]).first
79
+ @user = user_hash.target
80
+ unsubscribe = NotifyUser::Unsubscribe.create(target: @user, type: params[:type])
81
+ user_hash.deactivate
82
+ return render :text => "successfully unsubscribed from #{params[:type]} notifications"
83
+ else
84
+ return render :text => "invalid token"
85
+ end
86
+ end
87
+ return render :text => "Something went wrong please try again later"
88
+ end
89
+
90
+ def subscribe
91
+ subscribe_to(params[:type]) if params[:type]
92
+ redirect_to notify_user_notifications_unsubscribe_path
93
+ end
94
+
95
+ protected
96
+
97
+ def default_serializer_options
98
+ {
99
+ each_serializer: NotifyUser::NotificationSerializer,
100
+ template_renderer: self
101
+ }
102
+ end
103
+
104
+ def authenticate!
105
+ method(NotifyUser.authentication_method).call
106
+ @user = method(NotifyUser.current_user_method).call
107
+ end
108
+
109
+ private
110
+ def build_notification_types()
111
+ #dirty way to build a json hash with pagination
112
+ types = {:subscriptions => []}
113
+
114
+ notification_types = NotifyUser.unsubscribable_notifications
115
+
116
+ #iterates over channels
117
+ NotifyUser::BaseNotification.channels.each do |type, options|
118
+ channel = (type.to_s + "_channel").camelize.constantize
119
+ types[:subscriptions] << {type: type, description: channel.default_options[:description],
120
+ status: NotifyUser::Unsubscribe.has_unsubscribed_from(@user, type).empty?}
121
+ end
122
+
123
+ #iterates over type
124
+ notification_types.each do |type|
125
+ types[:subscriptions] << {type: type, description: type.constantize.description,
126
+ status: NotifyUser::Unsubscribe.has_unsubscribed_from(@user, type).empty?}
127
+ end
128
+ return types
129
+ end
130
+
131
+ def unsubscribe_from(type)
132
+ unsubscribe = NotifyUser::Unsubscribe.new(target: @user, type: type)
133
+ if unsubscribe.save
134
+ flash[:message] = "successfully unsubscribed from #{type} notifications"
135
+ else
136
+ flash[:message] = "Please try again"
137
+ end
138
+ end
139
+
140
+ def subscribe_to(type)
141
+ NotifyUser::Unsubscribe.unsubscribe(@user,type)
142
+ flash[:message] = "successfully subscribed to #{type} notifications"
143
+ end
144
+ end
@@ -1,33 +1,8 @@
1
- class NotifyUser::NotificationsController < ApplicationController
2
-
3
- before_filter :authenticate!
4
-
5
- def index
6
- @notifications = NotifyUser::BaseNotification.for_target(@user)
7
- .order("created_at DESC")
8
- .limit(30)
9
- .page(params[:page])
10
-
11
- render json: @notifications
12
- end
13
-
14
- def mark_read
15
- @notifications = NotifyUser::BaseNotification.for_target(@user).where('id IN (?)', params[:ids])
16
- @notifications.update_all(state: :read)
17
- render json: @notifications
18
- end
19
-
20
- protected
21
-
22
- def default_serializer_options
23
- {
24
- each_serializer: NotifyUser::NotificationSerializer,
25
- template_renderer: self
26
- }
27
- end
28
-
29
- def authenticate!
30
- method(NotifyUser.authentication_method).call
31
- @user = method(NotifyUser.current_user_method).call
32
- end
1
+ class NotifyUser::NotificationsController < NotifyUser::BaseNotificationsController
2
+ def redirect_logic(notification)
3
+ render :text => "set redirect logic in notify_user/notifications_controller.rb"
4
+ #notification redirect logic goes here
5
+ #property = Property.find(@notification.params[:property_id])
6
+ #redirect_to property_url(@property)
7
+ end
33
8
  end
@@ -1,4 +1,13 @@
1
1
  module NotifyUser
2
2
  module ApplicationHelper
3
+ def unsubscribe_link(notification, text)
4
+ user_hash = notification.generate_unsubscribe_hash
5
+ html = link_to(text, notify_user_notifications_unauth_unsubscribe_url(:type => notification.type, :token => user_hash.token))
6
+ return html.to_s.html_safe
7
+ end
8
+
9
+ def is_unsubscribeable?(notification)
10
+ return NotifyUser.unsubscribable_notifications.include? notification.type
11
+ end
3
12
  end
4
13
  end
@@ -1,5 +1,6 @@
1
1
  module NotifyUser
2
2
  class NotificationMailer < ActionMailer::Base
3
+ helper NotifyUser::ApplicationHelper
3
4
 
4
5
  layout "notify_user/layouts/action_mailer"
5
6
 
@@ -15,6 +16,7 @@ module NotifyUser
15
16
 
16
17
  def aggregate_notifications_email(notifications, options)
17
18
  @notifications = notifications
19
+ @notification = notifications.first
18
20
 
19
21
  mail to: @notifications.first.target.email,
20
22
  template_name: "aggregate_notification",
@@ -0,0 +1,37 @@
1
+ module NotifyUser
2
+ class Apns
3
+ SYMBOL_NAMES_SIZE = 10
4
+ PAYLOAD_LIMIT = 255
5
+
6
+ #sends push notification
7
+ def self.push_notification(notification)
8
+ #calculates the bytes already used
9
+ used_space = SYMBOL_NAMES_SIZE + notification.id.size + notification.created_at.to_time.to_i.size +
10
+ notification.type.size
11
+
12
+ used_space += notification.params[:action_id].size if notification.params[:action_id]
13
+
14
+ space_allowance = PAYLOAD_LIMIT - used_space
15
+
16
+ payload = {
17
+ :alias => notification.target_id,
18
+ :aps => {alert: notification.mobile_message(space_allowance), badge: 1},
19
+ :n_data => {
20
+ '#' => notification.id,
21
+ t: notification.created_at.to_time.to_i,
22
+ '?' => notification.type
23
+ }
24
+ }
25
+ payload[:n_data]['!'] = notification.params[:action_id] if notification.params[:action_id]
26
+
27
+ response = Urbanairship.push(payload)
28
+ if response.success?
29
+ puts "Push notification sent successfully."
30
+ return true
31
+ else
32
+ puts "Push notification failed."
33
+ return false
34
+ end
35
+ end
36
+ end
37
+ end
@@ -3,6 +3,7 @@ require 'sidekiq'
3
3
 
4
4
  module NotifyUser
5
5
  class BaseNotification < ActiveRecord::Base
6
+ include ActionView::Helpers::TextHelper
6
7
 
7
8
  if ActiveRecord::VERSION::MAJOR < 4
8
9
  attr_accessible :params, :target, :type, :state
@@ -11,8 +12,11 @@ module NotifyUser
11
12
  # Override point in case of collisions, plus keeps the table name tidy.
12
13
  self.table_name = "notify_user_notifications"
13
14
 
15
+ #checks if user has unsubscribed from this notif type
16
+ validate :unsubscribed_validation
17
+
14
18
  # Params for creating the notification message.
15
- serialize :params, Hash
19
+ # serialize :params, Hash
16
20
 
17
21
  # The user to send the notification to
18
22
  belongs_to :target, polymorphic: true
@@ -46,8 +50,29 @@ module NotifyUser
46
50
  end
47
51
  end
48
52
 
49
- ## Public Interface
53
+ def params
54
+ if super.nil?
55
+ {}
56
+ else
57
+ super.with_indifferent_access
58
+ end
59
+ end
60
+
61
+ def message
62
+ ActionView::Base.new(
63
+ Rails.configuration.paths["app/views"]).render(
64
+ :template => self.class.views[:mobile_sdk][:template_path].call(self), :formats => [:html],
65
+ :locals => { :params => self.params}, :layout => false)
66
+ end
50
67
 
68
+ def mobile_message(length=115)
69
+ truncate(ActionView::Base.new(
70
+ Rails.configuration.paths["app/views"]).render(
71
+ :template => self.class.views[:mobile_sdk][:template_path].call(self), :formats => [:html],
72
+ :locals => { :params => self.params}, :layout => false), :length => length)
73
+ end
74
+
75
+ ## Public Interface
51
76
  def to(user)
52
77
  self.target = user
53
78
  self
@@ -59,7 +84,7 @@ module NotifyUser
59
84
  end
60
85
 
61
86
  def notify!
62
- save!
87
+ save
63
88
 
64
89
  # Bang version of 'notify' ignores aggregation
65
90
  self.deliver!
@@ -68,29 +93,35 @@ module NotifyUser
68
93
  # Send any Emails/SMS/APNS
69
94
  def notify
70
95
 
71
- save!
72
-
73
- if self.class.aggregate_per
74
-
75
- # Schedule to send later if there aren't already any scheduled.
76
- # Otherwise ignore, as the already-scheduled aggregate job will pick this one up when it runs.
77
- if not aggregation_pending?
96
+ save
78
97
 
79
- # Send in X minutes, along with any others created in the intervening times.
80
- self.class.delay_for(self.class.aggregate_per).notify_aggregated(self.id)
98
+ #if aggregation is false bypass aggregation completely
99
+ self.channels.each do |channel_name, options|
100
+ if(options[:aggregate_per] == false)
101
+ self.class.delay.deliver_notification_channel(self.id, channel_name)
102
+ else
103
+ if not aggregation_pending?
104
+ self.class.delay_for(options[:aggregate_per] || self.aggregate_per).notify_aggregated_channel(self.id, channel_name)
105
+ end
81
106
  end
82
- else
83
- # No aggregation, send immediately.
84
- self.deliver
85
107
  end
86
108
 
87
109
  end
88
110
 
111
+ def generate_unsubscribe_hash
112
+ #check if a hash already exists for that user otherwise create a new one
113
+ return NotifyUser::UserHash.where(target_id: self.target.id).where(target_type: self.target.class.base_class).where(type: self.type).where(active: true).first || NotifyUser::UserHash.create(target: self.target, type: self.type, active: true)
114
+ end
115
+
116
+ ## Notification description
117
+ class_attribute :description
118
+ self.description = ""
119
+
89
120
  ## Channels
90
121
 
91
122
  mattr_accessor :channels
92
123
  @@channels = {
93
- action_mailer: {},
124
+ action_mailer: {description: 'Email notifications'}
94
125
  }
95
126
 
96
127
  # Not sure about this. The JSON and web feeds don't fit into channels, because nothing is broadcast through
@@ -109,14 +140,14 @@ module NotifyUser
109
140
 
110
141
  ## Aggregation
111
142
 
112
- mattr_accessor :aggregate_per
113
- @@aggregate_per = 1.minute
143
+ class_attribute :aggregate_per
144
+ self.aggregate_per = 1.minute
114
145
 
115
146
  ## Sending
116
147
 
117
148
  def self.for_target(target)
118
149
  where(target_id: target.id)
119
- .where(target_type: target.class.name)
150
+ .where(target_type: target.class.base_class)
120
151
  end
121
152
 
122
153
  def self.pending_aggregation_with(notification)
@@ -131,35 +162,88 @@ module NotifyUser
131
162
  return (self.class.pending_aggregation_with(self).where('id != ?', id).count > 0)
132
163
  end
133
164
 
134
- def deliver
135
- self.mark_as_sent
136
- self.save
165
+ # def deliver
166
+ # unless user_has_unsubscribed?
167
+ # self.mark_as_sent
168
+ # self.save
137
169
 
138
- self.class.delay.deliver_channels(self.id)
139
- end
170
+ # self.class.delay.deliver_channels(self.id)
171
+ # end
172
+ # end
140
173
 
141
174
  def deliver!
142
- self.mark_as_sent
143
- self.save
144
- self.class.deliver_channels(self.id)
175
+ unless user_has_unsubscribed?
176
+ self.mark_as_sent
177
+ self.save
178
+ self.class.deliver_channels(self.id)
179
+ end
145
180
  end
146
181
 
147
182
  # Deliver a single notification across each channel.
148
183
  def self.deliver_channels(notification_id)
149
184
  notification = self.where(id: notification_id).first
150
185
  return unless notification
151
-
152
186
  self.channels.each do |channel_name, options|
153
- channel = (channel_name.to_s + "_channel").camelize.constantize
154
- channel.deliver(notification, options)
187
+ unless unsubscribed_from_channel?(notification.target, channel_name)
188
+ channel = (channel_name.to_s + "_channel").camelize.constantize
189
+ channel.deliver(notification, options)
190
+ end
155
191
  end
156
192
  end
157
193
 
158
194
  # Deliver multiple notifications across each channel as an aggregate message.
159
195
  def self.deliver_channels_aggregated(notifications)
160
196
  self.channels.each do |channel_name, options|
161
- channel = (channel_name.to_s + "_channel").camelize.constantize
162
- channel.deliver_aggregated(notifications, options)
197
+ if options[:aggregate_per] != false && !unsubscribed_from_channel?(notifications.first.target, channel_name)
198
+ channel = (channel_name.to_s + "_channel").camelize.constantize
199
+ channel.deliver_aggregated(notifications, options)
200
+ end
201
+ end
202
+ end
203
+
204
+ #deliver to specific channel methods
205
+
206
+ # Deliver a single notification to a specific channel.
207
+ def self.deliver_notification_channel(notification_id, channel_name)
208
+ notification = self.where(id: notification_id).first
209
+ return unless notification
210
+ channel_options = channels[channel_name.to_sym]
211
+
212
+ channel = (channel_name.to_s + "_channel").camelize.constantize
213
+ unless self.unsubscribed_from_channel?(notification.target, channel_name)
214
+ channel.deliver(notification, channel_options)
215
+ end
216
+ end
217
+
218
+ # Deliver a aggregated notifications to a specific channel.
219
+ def self.deliver_notifications_channel(notifications, channel_name)
220
+ channel_options = channels[channel_name.to_sym]
221
+ channel = (channel_name.to_s + "_channel").camelize.constantize
222
+
223
+ #check if user unsubsribed from channel type
224
+ unless self.unsubscribed_from_channel?(notifications.first.target, channel_name)
225
+ channel.deliver_aggregated(notifications, channel_options)
226
+ end
227
+ end
228
+
229
+ #notifies a single channel for aggregation
230
+ def self.notify_aggregated_channel(notification_id, channel_name)
231
+ notification = self.find(notification_id) # Raise an exception if not found.
232
+
233
+ # Find any pending notifications with the same type and target, which can all be sent in one message.
234
+ notifications = self.pending_aggregation_with(notification)
235
+
236
+ notifications.map(&:mark_as_sent)
237
+ notifications.map(&:save)
238
+
239
+ return if notifications.empty?
240
+
241
+ if notifications.length == 1
242
+ # Despite waiting for more to aggregate, we only got one in the end.
243
+ self.deliver_notification_channel(notifications.first.id, channel_name)
244
+ else
245
+ # We got several notifications while waiting, send them aggregated.
246
+ self.deliver_notifications_channel(notifications, channel_name)
163
247
  end
164
248
  end
165
249
 
@@ -183,5 +267,25 @@ module NotifyUser
183
267
  end
184
268
  end
185
269
 
270
+ private
271
+ def unsubscribed_validation
272
+ errors.add(:target, (" has unsubscribed from this type")) if user_has_unsubscribed?
273
+ end
274
+
275
+ def user_has_unsubscribed?
276
+ #return true if user has unsubscribed
277
+ return true unless NotifyUser::Unsubscribe.has_unsubscribed_from(self.target, self.type).empty?
278
+
279
+ return false
280
+ end
281
+
282
+ def self.unsubscribed_from_channel?(user, type)
283
+ #return true if user has unsubscribed
284
+ return true unless NotifyUser::Unsubscribe.has_unsubscribed_from(user, type).empty?
285
+
286
+ return false
287
+ end
288
+
289
+
186
290
  end
187
291
  end