activity_notification 1.2.1 → 1.3.0
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.
- checksums.yaml +4 -4
- data/.travis.yml +15 -5
- data/CHANGELOG.md +13 -2
- data/Gemfile +1 -1
- data/Gemfile.lock +78 -71
- data/README.md +64 -43
- data/activity_notification.gemspec +5 -4
- data/app/controllers/activity_notification/notifications_controller.rb +1 -1
- data/app/controllers/activity_notification/subscriptions_controller.rb +1 -1
- data/gemfiles/Gemfile.rails-4.2 +1 -1
- data/gemfiles/Gemfile.rails-4.2.lock +71 -62
- data/gemfiles/Gemfile.rails-5.0 +1 -1
- data/gemfiles/Gemfile.rails-5.0.lock +74 -67
- data/lib/activity_notification.rb +9 -2
- data/lib/activity_notification/apis/notification_api.rb +142 -76
- data/lib/activity_notification/apis/subscription_api.rb +72 -0
- data/lib/activity_notification/config.rb +12 -0
- data/lib/activity_notification/models/concerns/notifiable.rb +56 -6
- data/lib/activity_notification/models/concerns/notifier.rb +8 -1
- data/lib/activity_notification/models/concerns/subscriber.rb +13 -10
- data/lib/activity_notification/models/concerns/target.rb +7 -5
- data/lib/activity_notification/models/notification.rb +2 -270
- data/lib/activity_notification/models/subscription.rb +3 -101
- data/lib/activity_notification/optional_targets/base.rb +5 -1
- data/lib/activity_notification/orm/active_record.rb +16 -0
- data/lib/activity_notification/orm/active_record/notification.rb +252 -0
- data/lib/activity_notification/orm/active_record/subscription.rb +52 -0
- data/lib/activity_notification/orm/mongoid.rb +63 -0
- data/lib/activity_notification/orm/mongoid/notification.rb +255 -0
- data/lib/activity_notification/orm/mongoid/subscription.rb +73 -0
- data/lib/activity_notification/rails/routes.rb +7 -3
- data/lib/activity_notification/renderable.rb +5 -1
- data/lib/activity_notification/roles/acts_as_notifiable.rb +4 -18
- data/lib/activity_notification/version.rb +1 -1
- data/lib/generators/activity_notification/install_generator.rb +3 -5
- data/lib/generators/templates/activity_notification.rb +9 -4
- data/spec/concerns/apis/notification_api_spec.rb +27 -14
- data/spec/concerns/models/notifiable_spec.rb +10 -8
- data/spec/concerns/models/subscriber_spec.rb +12 -12
- data/spec/concerns/models/target_spec.rb +61 -51
- data/spec/controllers/subscriptions_controller_shared_examples.rb +0 -1
- data/spec/helpers/view_helpers_spec.rb +24 -7
- data/spec/models/notification_spec.rb +63 -52
- data/spec/models/subscription_spec.rb +6 -3
- data/spec/optional_targets/amazon_sns_spec.rb +8 -5
- data/spec/optional_targets/base_spec.rb +3 -1
- data/spec/optional_targets/slack_spec.rb +5 -5
- data/spec/rails_app/app/models/comment.rb +1 -1
- data/spec/rails_app/app/views/activity_notification/notifications/users/overriden/custom/_test.html.erb +1 -0
- data/spec/rails_app/config/application.rb +7 -0
- data/spec/rails_app/config/initializers/activity_notification.rb +5 -0
- data/spec/rails_app/config/mongoid.yml +13 -0
- data/spec/rails_app/db/seeds.rb +1 -1
- data/spec/rails_app/lib/custom_optional_targets/console_output.rb +7 -4
- data/spec/rails_app/lib/custom_optional_targets/wrong_target.rb +3 -0
- data/spec/roles/acts_as_notifiable_spec.rb +77 -16
- data/spec/spec_helper.rb +7 -0
- metadata +38 -14
@@ -7,9 +7,7 @@ module ActivityNotification
|
|
7
7
|
extend ActiveSupport::Autoload
|
8
8
|
|
9
9
|
autoload :Notification, 'activity_notification/models/notification'
|
10
|
-
autoload :NotificationApi, 'activity_notification/apis/notification_api'
|
11
10
|
autoload :Subscription, 'activity_notification/models/subscription'
|
12
|
-
autoload :SubscriptionApi, 'activity_notification/apis/subscription_api'
|
13
11
|
autoload :Target, 'activity_notification/models/concerns/target'
|
14
12
|
autoload :Subscriber, 'activity_notification/models/concerns/subscriber'
|
15
13
|
autoload :Notifiable, 'activity_notification/models/concerns/notifiable'
|
@@ -44,8 +42,17 @@ module ActivityNotification
|
|
44
42
|
# end
|
45
43
|
def self.configure
|
46
44
|
yield(config) if block_given?
|
45
|
+
autoload :Association, "activity_notification/orm/#{ActivityNotification.config.orm}"
|
47
46
|
end
|
48
47
|
|
48
|
+
# Method used to choose which ORM to load
|
49
|
+
# when ActivityNotification::Notification class or ActivityNotification::Subscription class
|
50
|
+
# are being autoloaded
|
51
|
+
def self.inherit_orm(model)
|
52
|
+
orm = ActivityNotification.config.orm
|
53
|
+
require "activity_notification/orm/#{orm}"
|
54
|
+
"ActivityNotification::ORM::#{orm.to_s.classify}::#{model}".constantize
|
55
|
+
end
|
49
56
|
end
|
50
57
|
|
51
58
|
# Load ActivityNotification helpers
|
@@ -6,6 +6,131 @@ module ActivityNotification
|
|
6
6
|
included do
|
7
7
|
# Defines store_notification as private clas method
|
8
8
|
private_class_method :store_notification
|
9
|
+
|
10
|
+
# Selects all notification index.
|
11
|
+
# ActivityNotification::Notification.all_index!
|
12
|
+
# is defined same as
|
13
|
+
# ActivityNotification::Notification.group_owners_only.latest_order
|
14
|
+
# @scope class
|
15
|
+
# @example Get all notification index of the @user
|
16
|
+
# @notifications = @user.notifications.all_index!
|
17
|
+
# @notifications = @user.notifications.group_owners_only.latest_order
|
18
|
+
# @param [Boolean] reverse If notification index will be ordered as earliest first
|
19
|
+
# @param [Boolean] with_group_members If notification index will include group members
|
20
|
+
# @return [ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] Database query of filtered notifications
|
21
|
+
scope :all_index!, ->(reverse = false, with_group_members = false) {
|
22
|
+
target_index = with_group_members ? self : group_owners_only
|
23
|
+
reverse ? target_index.earliest_order : target_index.latest_order
|
24
|
+
}
|
25
|
+
|
26
|
+
# Selects unopened notification index.
|
27
|
+
# ActivityNotification::Notification.unopened_index
|
28
|
+
# is defined same as
|
29
|
+
# ActivityNotification::Notification.unopened_only.group_owners_only.latest_order
|
30
|
+
# @scope class
|
31
|
+
# @example Get unopened notificaton index of the @user
|
32
|
+
# @notifications = @user.notifications.unopened_index
|
33
|
+
# @notifications = @user.notifications.unopened_only.group_owners_only.latest_order
|
34
|
+
# @param [Boolean] reverse If notification index will be ordered as earliest first
|
35
|
+
# @param [Boolean] with_group_members If notification index will include group members
|
36
|
+
# @return [ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] Database query of filtered notifications
|
37
|
+
scope :unopened_index, ->(reverse = false, with_group_members = false) {
|
38
|
+
target_index = with_group_members ? unopened_only : unopened_only.group_owners_only
|
39
|
+
reverse ? target_index.earliest_order : target_index.latest_order
|
40
|
+
}
|
41
|
+
|
42
|
+
# Selects unopened notification index.
|
43
|
+
# ActivityNotification::Notification.opened_index(limit)
|
44
|
+
# is defined same as
|
45
|
+
# ActivityNotification::Notification.opened_only(limit).group_owners_only.latest_order
|
46
|
+
# @scope class
|
47
|
+
# @example Get unopened notificaton index of the @user with limit 10
|
48
|
+
# @notifications = @user.notifications.opened_index(10)
|
49
|
+
# @notifications = @user.notifications.opened_only(10).group_owners_only.latest_order
|
50
|
+
# @param [Integer] limit Limit to query for opened notifications
|
51
|
+
# @param [Boolean] reverse If notification index will be ordered as earliest first
|
52
|
+
# @param [Boolean] with_group_members If notification index will include group members
|
53
|
+
# @return [ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] Database query of filtered notifications
|
54
|
+
scope :opened_index, ->(limit, reverse = false, with_group_members = false) {
|
55
|
+
target_index = with_group_members ? opened_only(limit) : opened_only(limit).group_owners_only
|
56
|
+
reverse ? target_index.earliest_order : target_index.latest_order
|
57
|
+
}
|
58
|
+
|
59
|
+
# Selects filtered notifications by target_type.
|
60
|
+
# @example Get filtered unopened notificatons of User as target type
|
61
|
+
# @notifications = ActivityNotification.Notification.unopened_only.filtered_by_target_type('User')
|
62
|
+
# @scope class
|
63
|
+
# @param [String] target_type Target type for filter
|
64
|
+
# @return [ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] Database query of filtered notifications
|
65
|
+
scope :filtered_by_target_type, ->(target_type) { where(target_type: target_type) }
|
66
|
+
|
67
|
+
# Selects filtered notifications by notifiable_type.
|
68
|
+
# @example Get filtered unopened notificatons of the @user for Comment notifiable class
|
69
|
+
# @notifications = @user.notifications.unopened_only.filtered_by_type('Comment')
|
70
|
+
# @scope class
|
71
|
+
# @param [String] notifiable_type Notifiable type for filter
|
72
|
+
# @return [ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] Database query of filtered notifications
|
73
|
+
scope :filtered_by_type, ->(notifiable_type) { where(notifiable_type: notifiable_type) }
|
74
|
+
|
75
|
+
# Selects filtered notifications by key.
|
76
|
+
# @example Get filtered unopened notificatons of the @user with key 'comment.reply'
|
77
|
+
# @notifications = @user.notifications.unopened_only.filtered_by_key('comment.reply')
|
78
|
+
# @scope class
|
79
|
+
# @param [String] key Key of the notification for filter
|
80
|
+
# @return [ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] Database query of filtered notifications
|
81
|
+
scope :filtered_by_key, ->(key) { where(key: key) }
|
82
|
+
|
83
|
+
# Selects filtered notifications by notifiable_type, group or key with filter options.
|
84
|
+
# @example Get filtered unopened notificatons of the @user for Comment notifiable class
|
85
|
+
# @notifications = @user.notifications.unopened_only.filtered_by_options({ filtered_by_type: 'Comment' })
|
86
|
+
# @example Get filtered unopened notificatons of the @user for @article as group
|
87
|
+
# @notifications = @user.notifications.unopened_only.filtered_by_options({ filtered_by_group: @article })
|
88
|
+
# @example Get filtered unopened notificatons of the @user for Article instance id=1 as group
|
89
|
+
# @notifications = @user.notifications.unopened_only.filtered_by_options({ filtered_by_group_type: 'Article', filtered_by_group_id: '1' })
|
90
|
+
# @example Get filtered unopened notificatons of the @user with key 'comment.reply'
|
91
|
+
# @notifications = @user.notifications.unopened_only.filtered_by_options({ filtered_by_key: 'comment.reply' })
|
92
|
+
# @example Get filtered unopened notificatons of the @user for Comment notifiable class with key 'comment.reply'
|
93
|
+
# @notifications = @user.notifications.unopened_only.filtered_by_options({ filtered_by_type: 'Comment', filtered_by_key: 'comment.reply' })
|
94
|
+
# @example Get custom filtered notificatons of the @user
|
95
|
+
# @notifications = @user.notifications.unopened_only.filtered_by_options({ custom_filter: ["created_at >= ?", time.hour.ago] })
|
96
|
+
# @scope class
|
97
|
+
# @param [Hash] options Options for filter
|
98
|
+
# @option options [String] :filtered_by_type (nil) Notifiable type for filter
|
99
|
+
# @option options [Object] :filtered_by_group (nil) Group instance for filter
|
100
|
+
# @option options [String] :filtered_by_group_type (nil) Group type for filter, valid with :filtered_by_group_id
|
101
|
+
# @option options [String] :filtered_by_group_id (nil) Group instance id for filter, valid with :filtered_by_group_type
|
102
|
+
# @option options [String] :filtered_by_key (nil) Key of the notification for filter
|
103
|
+
# @option options [Array|Hash] :custom_filter (nil) Custom notification filter (e.g. ["created_at >= ?", time.hour.ago])
|
104
|
+
# @return [ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] Database query of filtered notifications
|
105
|
+
scope :filtered_by_options, ->(options = {}) {
|
106
|
+
options = ActivityNotification.cast_to_indifferent_hash(options)
|
107
|
+
filtered_notifications = all
|
108
|
+
if options.has_key?(:filtered_by_type)
|
109
|
+
filtered_notifications = filtered_notifications.filtered_by_type(options[:filtered_by_type])
|
110
|
+
end
|
111
|
+
if options.has_key?(:filtered_by_group)
|
112
|
+
filtered_notifications = filtered_notifications.filtered_by_group(options[:filtered_by_group])
|
113
|
+
end
|
114
|
+
if options.has_key?(:filtered_by_group_type) && options.has_key?(:filtered_by_group_id)
|
115
|
+
filtered_notifications = filtered_notifications
|
116
|
+
.where(group_type: options[:filtered_by_group_type], group_id: options[:filtered_by_group_id])
|
117
|
+
end
|
118
|
+
if options.has_key?(:filtered_by_key)
|
119
|
+
filtered_notifications = filtered_notifications.filtered_by_key(options[:filtered_by_key])
|
120
|
+
end
|
121
|
+
if options.has_key?(:custom_filter)
|
122
|
+
filtered_notifications = filtered_notifications.where(options[:custom_filter])
|
123
|
+
end
|
124
|
+
filtered_notifications
|
125
|
+
}
|
126
|
+
|
127
|
+
# Orders by latest (newest) first as created_at: :desc.
|
128
|
+
# @return [Mongoid::Criteria<Notificaion>] Database query of notifications ordered by latest first
|
129
|
+
scope :latest_order, -> { order(created_at: :desc) }
|
130
|
+
|
131
|
+
# Orders by earliest (older) first as created_at: :asc.
|
132
|
+
# @return [Mongoid::Criteria<Notificaion>] Database query of notifications ordered by earliest first
|
133
|
+
scope :earliest_order, -> { order(created_at: :asc) }
|
9
134
|
end
|
10
135
|
|
11
136
|
class_methods do
|
@@ -129,16 +254,19 @@ module ActivityNotification
|
|
129
254
|
# @todo Add filter option
|
130
255
|
def open_all_of(target, options = {})
|
131
256
|
opened_at = options[:opened_at] || Time.current
|
132
|
-
target.notifications.unopened_only.filtered_by_options(options)
|
257
|
+
target_unopened_notifications = target.notifications.unopened_only.filtered_by_options(options)
|
258
|
+
unopened_notification_count = target_unopened_notifications.count
|
259
|
+
target_unopened_notifications.update_all(opened_at: opened_at)
|
260
|
+
unopened_notification_count
|
133
261
|
end
|
134
262
|
|
135
263
|
# Returns if group member of the notifications exists.
|
136
264
|
# This method is designed to be called from controllers or views to avoid N+1.
|
137
265
|
#
|
138
|
-
# @param [Array<Notificaion>, ActiveRecord_AssociationRelation<Notificaion>] notifications Array or database query of the notifications to test member exists
|
266
|
+
# @param [Array<Notificaion>, ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] notifications Array or database query of the notifications to test member exists
|
139
267
|
# @return [Boolean] If group member of the notifications exists
|
140
268
|
def group_member_exists?(notifications)
|
141
|
-
notifications.present? &&
|
269
|
+
notifications.present? && group_members_of_owner_ids_only(notifications.map(&:id)).exists?
|
142
270
|
end
|
143
271
|
|
144
272
|
# Sends batch notification email to the target.
|
@@ -181,16 +309,15 @@ module ActivityNotification
|
|
181
309
|
parameters.merge!(notifiable.notification_parameters(target_type, key))
|
182
310
|
|
183
311
|
# Bundle notification group by target, notifiable_type, group and key
|
184
|
-
#
|
312
|
+
# Different notifiable.id can be made in a same group
|
185
313
|
group_owner_notifications = filtered_by_target(target).filtered_by_type(notifiable.to_class_name).filtered_by_key(key)
|
186
314
|
.filtered_by_group(group).group_owners_only.unopened_only
|
187
315
|
group_owner = group_expiry_delay.present? ?
|
188
|
-
group_owner_notifications.
|
316
|
+
group_owner_notifications.within_expiration_only(group_expiry_delay).earliest :
|
189
317
|
group_owner_notifications.earliest
|
190
318
|
notification_fields = { target: target, notifiable: notifiable, key: key, group: group, parameters: parameters, notifier: notifier }
|
191
|
-
group.present? && group_owner.present?
|
192
|
-
|
193
|
-
create(notification_fields)
|
319
|
+
notification_fields = notification_fields.merge(group_owner: group_owner) if group.present? && group_owner.present?
|
320
|
+
create(notification_fields)
|
194
321
|
end
|
195
322
|
end
|
196
323
|
|
@@ -235,10 +362,13 @@ module ActivityNotification
|
|
235
362
|
# @option options [Boolean] :with_members (true) If it opens notifications including group members
|
236
363
|
# @return [Integer] Number of opened notification records
|
237
364
|
def open!(options = {})
|
238
|
-
|
365
|
+
opened? and return 0
|
366
|
+
opened_at = options[:opened_at] || Time.current
|
239
367
|
with_members = options.has_key?(:with_members) ? options[:with_members] : true
|
368
|
+
unopened_member_count = with_members ? group_members.unopened_only.count : 0
|
369
|
+
group_members.update_all(opened_at: opened_at) if with_members
|
240
370
|
update(opened_at: opened_at)
|
241
|
-
|
371
|
+
unopened_member_count + 1
|
242
372
|
end
|
243
373
|
|
244
374
|
# Returns if the notification is unopened.
|
@@ -259,7 +389,7 @@ module ActivityNotification
|
|
259
389
|
#
|
260
390
|
# @return [Boolean] If the notification is group owner
|
261
391
|
def group_owner?
|
262
|
-
|
392
|
+
!group_member?
|
263
393
|
end
|
264
394
|
|
265
395
|
# Returns if the notification is group member belonging to owner.
|
@@ -345,7 +475,7 @@ module ActivityNotification
|
|
345
475
|
new_group_owner = group_members.earliest
|
346
476
|
if new_group_owner.present?
|
347
477
|
new_group_owner.update(group_owner_id: nil)
|
348
|
-
group_members.update_all(group_owner_id: new_group_owner)
|
478
|
+
group_members.update_all(group_owner_id: new_group_owner.id)
|
349
479
|
end
|
350
480
|
new_group_owner
|
351
481
|
end
|
@@ -391,70 +521,6 @@ module ActivityNotification
|
|
391
521
|
|
392
522
|
protected
|
393
523
|
|
394
|
-
# Returns count of group members of the unopened notification.
|
395
|
-
# This method is designed to cache group by query result to avoid N+1 call.
|
396
|
-
# @api protected
|
397
|
-
#
|
398
|
-
# @return [Integer] Count of group members of the unopened notification
|
399
|
-
def unopened_group_member_count
|
400
|
-
# Cache group by query result to avoid N+1 call
|
401
|
-
unopened_group_member_counts = target.notifications
|
402
|
-
.unopened_index_group_members_only
|
403
|
-
.group(:group_owner_id)
|
404
|
-
.count
|
405
|
-
unopened_group_member_counts[id] || 0
|
406
|
-
end
|
407
|
-
|
408
|
-
# Returns count of group members of the opened notification.
|
409
|
-
# This method is designed to cache group by query result to avoid N+1 call.
|
410
|
-
# @api protected
|
411
|
-
#
|
412
|
-
# @return [Integer] Count of group members of the opened notification
|
413
|
-
def opened_group_member_count(limit = ActivityNotification.config.opened_index_limit)
|
414
|
-
# Cache group by query result to avoid N+1 call
|
415
|
-
opened_group_member_counts = target.notifications
|
416
|
-
.opened_index_group_members_only(limit)
|
417
|
-
.group(:group_owner_id)
|
418
|
-
.count
|
419
|
-
opened_group_member_counts[id] || 0
|
420
|
-
end
|
421
|
-
|
422
|
-
# Returns count of group member notifiers of the unopened notification not including group owner notifier.
|
423
|
-
# This method is designed to cache group by query result to avoid N+1 call.
|
424
|
-
# @api protected
|
425
|
-
#
|
426
|
-
# @return [Integer] Count of group member notifiers of the unopened notification
|
427
|
-
def unopened_group_member_notifier_count
|
428
|
-
# Cache group by query result to avoid N+1 call
|
429
|
-
unopened_group_member_notifier_counts = target.notifications
|
430
|
-
.unopened_index_group_members_only
|
431
|
-
.includes(:group_owner)
|
432
|
-
.where('group_owners_notifications.notifier_type = notifications.notifier_type')
|
433
|
-
.where.not('group_owners_notifications.notifier_id = notifications.notifier_id')
|
434
|
-
.references(:group_owner)
|
435
|
-
.group(:group_owner_id, :notifier_type)
|
436
|
-
.count('distinct notifications.notifier_id')
|
437
|
-
unopened_group_member_notifier_counts[[id, notifier_type]] || 0
|
438
|
-
end
|
439
|
-
|
440
|
-
# Returns count of group member notifiers of the opened notification not including group owner notifier.
|
441
|
-
# This method is designed to cache group by query result to avoid N+1 call.
|
442
|
-
# @api protected
|
443
|
-
#
|
444
|
-
# @return [Integer] Count of group member notifiers of the opened notification
|
445
|
-
def opened_group_member_notifier_count(limit = ActivityNotification.config.opened_index_limit)
|
446
|
-
# Cache group by query result to avoid N+1 call
|
447
|
-
opened_group_member_notifier_counts = target.notifications
|
448
|
-
.opened_index_group_members_only(limit)
|
449
|
-
.includes(:group_owner)
|
450
|
-
.where('group_owners_notifications.notifier_type = notifications.notifier_type')
|
451
|
-
.where.not('group_owners_notifications.notifier_id = notifications.notifier_id')
|
452
|
-
.references(:group_owner)
|
453
|
-
.group(:group_owner_id, :notifier_type)
|
454
|
-
.count('distinct notifications.notifier_id')
|
455
|
-
opened_group_member_notifier_counts[[id, notifier_type]] || 0
|
456
|
-
end
|
457
|
-
|
458
524
|
# Returns count of various members of the notification.
|
459
525
|
# This method is designed to cache group by query result to avoid N+1 call.
|
460
526
|
# @api protected
|
@@ -3,6 +3,58 @@ module ActivityNotification
|
|
3
3
|
module SubscriptionApi
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
|
+
included do
|
7
|
+
# Selects filtered subscriptions by key.
|
8
|
+
# @example Get filtered subscriptions of the @user with key 'comment.reply'
|
9
|
+
# @subscriptions = @user.subscriptions.filtered_by_key('comment.reply')
|
10
|
+
# @scope class
|
11
|
+
# @param [String] key Key of the subscription for filter
|
12
|
+
# @return [ActiveRecord_AssociationRelation<Subscription>] Database query of filtered subscriptions
|
13
|
+
scope :filtered_by_key, ->(key) { where(key: key) }
|
14
|
+
|
15
|
+
# Selects filtered subscriptions by key with filter options.
|
16
|
+
# @example Get filtered subscriptions of the @user with key 'comment.reply'
|
17
|
+
# @subscriptions = @user.subscriptions.filtered_by_key('comment.reply')
|
18
|
+
# @example Get custom filtered subscriptions of the @user
|
19
|
+
# @subscriptions = @user.subscriptions.filtered_by_options({ custom_filter: ["created_at >= ?", time.hour.ago] })
|
20
|
+
# @scope class
|
21
|
+
# @param [Hash] options Options for filter
|
22
|
+
# @option options [String] :filtered_by_key (nil) Key of the subscription for filter
|
23
|
+
# @option options [Array|Hash] :custom_filter (nil) Custom subscription filter (e.g. ["created_at >= ?", time.hour.ago])
|
24
|
+
# @return [Mongoid::Criteria<Notificaion>] Database query of filtered subscriptions
|
25
|
+
scope :filtered_by_options, ->(options = {}) {
|
26
|
+
options = ActivityNotification.cast_to_indifferent_hash(options)
|
27
|
+
filtered_subscriptions = all
|
28
|
+
if options.has_key?(:filtered_by_key)
|
29
|
+
filtered_subscriptions = filtered_subscriptions.filtered_by_key(options[:filtered_by_key])
|
30
|
+
end
|
31
|
+
if options.has_key?(:custom_filter)
|
32
|
+
filtered_subscriptions = filtered_subscriptions.where(options[:custom_filter])
|
33
|
+
end
|
34
|
+
filtered_subscriptions
|
35
|
+
}
|
36
|
+
|
37
|
+
# Orders by latest (newest) first as created_at: :desc.
|
38
|
+
# @return [ActiveRecord_AssociationRelation<Subscription>] Database query of subscriptions ordered by latest first
|
39
|
+
scope :latest_order, -> { order(created_at: :desc) }
|
40
|
+
|
41
|
+
# Orders by earliest (older) first as created_at: :asc.
|
42
|
+
# @return [ActiveRecord_AssociationRelation<Subscription>] Database query of subscriptions ordered by earliest first
|
43
|
+
scope :earliest_order, -> { order(created_at: :asc) }
|
44
|
+
|
45
|
+
# Orders by latest (newest) first as subscribed_at: :desc.
|
46
|
+
# @return [ActiveRecord_AssociationRelation<Subscription>] Database query of subscriptions ordered by latest subscribed_at first
|
47
|
+
scope :latest_subscribed_order, -> { order(subscribed_at: :desc) }
|
48
|
+
|
49
|
+
# Orders by earliest (older) first as subscribed_at: :asc.
|
50
|
+
# @return [ActiveRecord_AssociationRelation<Subscription>] Database query of subscriptions ordered by earliest subscribed_at first
|
51
|
+
scope :earliest_subscribed_order, -> { order(subscribed_at: :asc) }
|
52
|
+
|
53
|
+
# Orders by key name as key: :asc.
|
54
|
+
# @return [ActiveRecord_AssociationRelation<Subscription>] Database query of subscriptions ordered by key name
|
55
|
+
scope :key_order, -> { order(key: :asc) }
|
56
|
+
end
|
57
|
+
|
6
58
|
class_methods do
|
7
59
|
# Returns key of optional_targets hash from symbol class name of the optional target implementation.
|
8
60
|
# @param [String, Symbol] optional_target_name Class name of the optional target implementation (e.g. :amazon_sns, :slack)
|
@@ -132,5 +184,25 @@ module ActivityNotification
|
|
132
184
|
def optional_target_names
|
133
185
|
optional_targets.keys.select { |key| key.to_s.start_with?("subscribing_to_") }.map { |key| key.slice(15..-1) }
|
134
186
|
end
|
187
|
+
|
188
|
+
|
189
|
+
protected
|
190
|
+
|
191
|
+
# Validates subscribing_to_email cannot be true when subscribing isfalse.
|
192
|
+
def subscribing_to_email_cannot_be_true_when_subscribing_is_false
|
193
|
+
if !subscribing && subscribing_to_email?
|
194
|
+
errors.add(:subscribing_to_email, "cannot be true when subscribing is false")
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
# Validates subscribing_to_optional_target cannot be true when subscribing isfalse.
|
199
|
+
def subscribing_to_optional_target_cannot_be_true_when_subscribing_is_false
|
200
|
+
optional_target_names.each do |optional_target_name|
|
201
|
+
if !subscribing && subscribing_to_optional_target?(optional_target_name)
|
202
|
+
errors.add(:optional_targets, "#Subscription.to_optional_target_key(optional_target_name) cannot be true when subscribing is false")
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
135
207
|
end
|
136
208
|
end
|
@@ -110,6 +110,11 @@ module ActivityNotification
|
|
110
110
|
# @return [Integer] Default limit to query for opened notifications.
|
111
111
|
attr_accessor :opened_index_limit
|
112
112
|
|
113
|
+
# @overload :orm
|
114
|
+
# Returns ORM name for ActivityNotification (:active_record or :mongoid)
|
115
|
+
# @return [Boolean] ORM name for ActivityNotification (:active_record or :mongoid).
|
116
|
+
attr_reader :orm
|
117
|
+
|
113
118
|
# Initialize configuration for ActivityNotification.
|
114
119
|
# These configuration can be overriden in initializer.
|
115
120
|
# @return [Config] A new instance of Config
|
@@ -125,7 +130,14 @@ module ActivityNotification
|
|
125
130
|
@parent_mailer = 'ActionMailer::Base'
|
126
131
|
@parent_controller = 'ApplicationController'
|
127
132
|
@opened_index_limit = 10
|
133
|
+
@orm = :active_record
|
128
134
|
end
|
129
135
|
|
136
|
+
# Sets ORM name for ActivityNotification (:active_record or :mongoid)
|
137
|
+
# @param [Symbol, String] orm The new ORM name for ActivityNotification (:active_record or :mongoid)
|
138
|
+
# @return [Symbol] ORM name for ActivityNotification (:active_record or :mongoid).
|
139
|
+
def orm=(orm)
|
140
|
+
@orm = orm.to_sym
|
141
|
+
end
|
130
142
|
end
|
131
143
|
end
|
@@ -7,14 +7,15 @@ module ActivityNotification
|
|
7
7
|
|
8
8
|
included do
|
9
9
|
include Common
|
10
|
+
include Association
|
10
11
|
include ActionDispatch::Routing::PolymorphicRoutes
|
11
12
|
include Rails.application.routes.url_helpers
|
12
13
|
|
13
14
|
# Has many notification instances for this notifiable.
|
14
15
|
# Dependency for these notifications can be overriden from acts_as_notifiable.
|
15
16
|
# @scope instance
|
16
|
-
# @return [Array<Notificaion>] Array or database query of notifications for this notifiable
|
17
|
-
|
17
|
+
# @return [Array<Notificaion>, Mongoid::Criteria<Notificaion>] Array or database query of notifications for this notifiable
|
18
|
+
has_many_records :generated_notifications_as_notifiable,
|
18
19
|
class_name: "::ActivityNotification::Notification",
|
19
20
|
as: :notifiable
|
20
21
|
|
@@ -207,8 +208,14 @@ module ActivityNotification
|
|
207
208
|
optional_targets(target_type, key).map { |optional_target| optional_target.to_optional_target_name }
|
208
209
|
end
|
209
210
|
|
211
|
+
# overriding_notification_template_key is the method to override key definition for Renderable
|
212
|
+
# When respond_to?(:overriding_notification_template_key) returns true,
|
213
|
+
# Renderable uses overriding_notification_template_key instead of original key.
|
214
|
+
#
|
215
|
+
# overriding_notification_template_key(target, key)
|
216
|
+
|
210
217
|
# overriding_notification_email_key is the method to override key definition for Mailer
|
211
|
-
# When respond_to?(overriding_notification_email_key) returns true,
|
218
|
+
# When respond_to?(:overriding_notification_email_key) returns true,
|
212
219
|
# Mailer uses overriding_notification_email_key instead of original key.
|
213
220
|
#
|
214
221
|
# overriding_notification_email_key(target, key)
|
@@ -303,11 +310,54 @@ module ActivityNotification
|
|
303
310
|
end
|
304
311
|
end
|
305
312
|
|
306
|
-
#
|
313
|
+
# Gets generated notifications for specified target type.
|
314
|
+
# @api private
|
315
|
+
# @param [String] target_type Target type of generated notifications
|
316
|
+
def generated_notifications_as_notifiable_for(target_type = nil)
|
317
|
+
target_type.nil? ?
|
318
|
+
generated_notifications_as_notifiable.all :
|
319
|
+
generated_notifications_as_notifiable.filtered_by_target_type(target_type.to_s.to_model_name)
|
320
|
+
end
|
321
|
+
|
322
|
+
# Destroies generated notifications for specified target type with dependency.
|
323
|
+
# This method is intended to be called before destroy this notifiable as dependent configuration.
|
324
|
+
# @api private
|
325
|
+
# @param [Symbol] dependent Has_many dependency, [:delete_all, :destroy, :restrict_with_error, :restrict_with_exception] are available
|
326
|
+
# @param [String] target_type Target type of generated notifications
|
327
|
+
# @param [Boolean] remove_from_group Whether it removes generated notifications from notification group before destroy
|
328
|
+
def destroy_generated_notifications_with_dependency(dependent = :delete_all, target_type = nil, remove_from_group = false)
|
329
|
+
remove_generated_notifications_from_group(target_type) if remove_from_group
|
330
|
+
generated_notifications = generated_notifications_as_notifiable_for(target_type)
|
331
|
+
case dependent
|
332
|
+
when :restrict_with_exception
|
333
|
+
raise ActiveRecord::DeleteRestrictionError.new("generated_notifications_as_notifiable_for_#{target_type.to_s.pluralize.underscore}") unless generated_notifications.empty?
|
334
|
+
when :restrict_with_error
|
335
|
+
unless generated_notifications.empty?
|
336
|
+
record = self.class.human_attribute_name("generated_notifications_as_notifiable_for_#{target_type.to_s.pluralize.underscore}").downcase
|
337
|
+
self.errors.add(:base, :'restrict_dependent_destroy.has_many', record: record)
|
338
|
+
# :skip-rails4:
|
339
|
+
if Rails::VERSION::MAJOR >= 5
|
340
|
+
throw(:abort)
|
341
|
+
# :skip-rails4:
|
342
|
+
# :skip-rails5:
|
343
|
+
else
|
344
|
+
false
|
345
|
+
end
|
346
|
+
# :skip-rails5:
|
347
|
+
end
|
348
|
+
when :destroy
|
349
|
+
generated_notifications.each { |n| n.destroy }
|
350
|
+
when :delete_all
|
351
|
+
generated_notifications.delete_all
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
# Removes generated notifications from notification group to new group owner.
|
307
356
|
# This method is intended to be called before destroy this notifiable as dependent configuration.
|
308
357
|
# @api private
|
309
|
-
|
310
|
-
|
358
|
+
# @param [String] target_type Target type of generated notifications
|
359
|
+
def remove_generated_notifications_from_group(target_type = nil)
|
360
|
+
generated_notifications_as_notifiable_for(target_type).group_owners_only.each { |n| n.remove_from_group }
|
311
361
|
end
|
312
362
|
|
313
363
|
# Casts to resources name.
|