activity_notification 2.5.1 → 2.6.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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -0
  3. data/app/channels/activity_notification/notification_api_channel.rb +5 -5
  4. data/app/channels/activity_notification/notification_api_with_devise_channel.rb +4 -4
  5. data/app/channels/activity_notification/notification_channel.rb +4 -0
  6. data/app/channels/activity_notification/notification_with_devise_channel.rb +4 -4
  7. data/app/controllers/activity_notification/notifications_controller.rb +1 -2
  8. data/app/controllers/activity_notification/subscriptions_controller.rb +2 -3
  9. data/app/jobs/activity_notification/notify_all_job.rb +2 -2
  10. data/app/jobs/activity_notification/notify_job.rb +2 -2
  11. data/app/jobs/activity_notification/notify_to_job.rb +1 -1
  12. data/app/mailers/activity_notification/mailer.rb +1 -1
  13. data/app/views/activity_notification/mailer/default/batch_default.text.erb +1 -1
  14. data/app/views/activity_notification/notifications/default/index.html.erb +1 -1
  15. data/app/views/activity_notification/subscriptions/default/_notification_keys.html.erb +1 -1
  16. data/app/views/activity_notification/subscriptions/default/_subscription.html.erb +1 -1
  17. data/docs/Functions.md +93 -9
  18. data/docs/Setup.md +7 -7
  19. data/docs/Testing.md +1 -1
  20. data/docs/Upgrade-to-2.6.md +108 -0
  21. data/lib/activity_notification/apis/notification_api.rb +55 -40
  22. data/lib/activity_notification/apis/subscription_api.rb +10 -10
  23. data/lib/activity_notification/common.rb +5 -5
  24. data/lib/activity_notification/config.rb +15 -5
  25. data/lib/activity_notification/controllers/common_controller.rb +2 -4
  26. data/lib/activity_notification/controllers/devise_authentication_controller.rb +2 -2
  27. data/lib/activity_notification/helpers/polymorphic_helpers.rb +6 -6
  28. data/lib/activity_notification/helpers/view_helpers.rb +3 -3
  29. data/lib/activity_notification/mailers/helpers.rb +88 -2
  30. data/lib/activity_notification/models/concerns/notifiable.rb +60 -30
  31. data/lib/activity_notification/models/concerns/notifier.rb +1 -1
  32. data/lib/activity_notification/models/concerns/subscriber.rb +72 -15
  33. data/lib/activity_notification/models/concerns/target.rb +38 -35
  34. data/lib/activity_notification/optional_targets/action_cable_api_channel.rb +1 -1
  35. data/lib/activity_notification/optional_targets/slack.rb +2 -2
  36. data/lib/activity_notification/orm/active_record/notification.rb +25 -25
  37. data/lib/activity_notification/orm/active_record/subscription.rb +21 -1
  38. data/lib/activity_notification/orm/dynamoid/extension.rb +3 -3
  39. data/lib/activity_notification/orm/dynamoid/subscription.rb +8 -1
  40. data/lib/activity_notification/orm/dynamoid.rb +18 -18
  41. data/lib/activity_notification/orm/mongoid/notification.rb +26 -28
  42. data/lib/activity_notification/orm/mongoid/subscription.rb +21 -1
  43. data/lib/activity_notification/orm/mongoid.rb +1 -1
  44. data/lib/activity_notification/rails/routes.rb +11 -11
  45. data/lib/activity_notification/roles/acts_as_group.rb +1 -1
  46. data/lib/activity_notification/roles/acts_as_notifiable.rb +5 -5
  47. data/lib/activity_notification/roles/acts_as_notifier.rb +1 -1
  48. data/lib/activity_notification/roles/acts_as_target.rb +1 -1
  49. data/lib/activity_notification/version.rb +1 -1
  50. data/lib/generators/activity_notification/add_notifiable_to_subscriptions/add_notifiable_to_subscriptions_generator.rb +23 -0
  51. data/lib/generators/activity_notification/add_notifiable_to_subscriptions/templates/add_notifiable_to_subscriptions.rb +13 -0
  52. data/lib/generators/templates/activity_notification.rb +14 -2
  53. data/lib/generators/templates/migrations/migration.rb +4 -2
  54. metadata +5 -2
@@ -25,7 +25,7 @@ module ActivityNotification
25
25
  # @notifications = @user.notifications.group_owners_only.latest_order
26
26
  # @param [Boolean] reverse If notification index will be ordered as earliest first
27
27
  # @param [Boolean] with_group_members If notification index will include group members
28
- # @return [ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] Database query of filtered notifications
28
+ # @return [ActiveRecord_AssociationRelation<Notification>, Mongoid::Criteria<Notification>] Database query of filtered notifications
29
29
  scope :all_index!, ->(reverse = false, with_group_members = false) {
30
30
  target_index = with_group_members ? self : group_owners_only
31
31
  reverse ? target_index.earliest_order : target_index.latest_order
@@ -36,12 +36,12 @@ module ActivityNotification
36
36
  # is defined same as
37
37
  # ActivityNotification::Notification.unopened_only.group_owners_only.latest_order
38
38
  # @scope class
39
- # @example Get unopened notificaton index of the @user
39
+ # @example Get unopened notification index of the @user
40
40
  # @notifications = @user.notifications.unopened_index
41
41
  # @notifications = @user.notifications.unopened_only.group_owners_only.latest_order
42
42
  # @param [Boolean] reverse If notification index will be ordered as earliest first
43
43
  # @param [Boolean] with_group_members If notification index will include group members
44
- # @return [ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] Database query of filtered notifications
44
+ # @return [ActiveRecord_AssociationRelation<Notification>, Mongoid::Criteria<Notification>] Database query of filtered notifications
45
45
  scope :unopened_index, ->(reverse = false, with_group_members = false) {
46
46
  target_index = with_group_members ? unopened_only : unopened_only.group_owners_only
47
47
  reverse ? target_index.earliest_order : target_index.latest_order
@@ -52,54 +52,54 @@ module ActivityNotification
52
52
  # is defined same as
53
53
  # ActivityNotification::Notification.opened_only(limit).group_owners_only.latest_order
54
54
  # @scope class
55
- # @example Get unopened notificaton index of the @user with limit 10
55
+ # @example Get unopened notification index of the @user with limit 10
56
56
  # @notifications = @user.notifications.opened_index(10)
57
57
  # @notifications = @user.notifications.opened_only(10).group_owners_only.latest_order
58
58
  # @param [Integer] limit Limit to query for opened notifications
59
59
  # @param [Boolean] reverse If notification index will be ordered as earliest first
60
60
  # @param [Boolean] with_group_members If notification index will include group members
61
- # @return [ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] Database query of filtered notifications
61
+ # @return [ActiveRecord_AssociationRelation<Notification>, Mongoid::Criteria<Notification>] Database query of filtered notifications
62
62
  scope :opened_index, ->(limit, reverse = false, with_group_members = false) {
63
63
  target_index = with_group_members ? opened_only(limit) : opened_only(limit).group_owners_only
64
64
  reverse ? target_index.earliest_order : target_index.latest_order
65
65
  }
66
66
 
67
67
  # Selects filtered notifications by target_type.
68
- # @example Get filtered unopened notificatons of User as target type
68
+ # @example Get filtered unopened notification of User as target type
69
69
  # @notifications = ActivityNotification.Notification.unopened_only.filtered_by_target_type('User')
70
70
  # @scope class
71
71
  # @param [String] target_type Target type for filter
72
- # @return [ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] Database query of filtered notifications
72
+ # @return [ActiveRecord_AssociationRelation<Notification>, Mongoid::Criteria<Notification>] Database query of filtered notifications
73
73
  scope :filtered_by_target_type, ->(target_type) { where(target_type: target_type) }
74
74
 
75
75
  # Selects filtered notifications by notifiable_type.
76
- # @example Get filtered unopened notificatons of the @user for Comment notifiable class
76
+ # @example Get filtered unopened notification of the @user for Comment notifiable class
77
77
  # @notifications = @user.notifications.unopened_only.filtered_by_type('Comment')
78
78
  # @scope class
79
79
  # @param [String] notifiable_type Notifiable type for filter
80
- # @return [ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] Database query of filtered notifications
80
+ # @return [ActiveRecord_AssociationRelation<Notification>, Mongoid::Criteria<Notification>] Database query of filtered notifications
81
81
  scope :filtered_by_type, ->(notifiable_type) { where(notifiable_type: notifiable_type) }
82
82
 
83
83
  # Selects filtered notifications by key.
84
- # @example Get filtered unopened notificatons of the @user with key 'comment.reply'
84
+ # @example Get filtered unopened notification of the @user with key 'comment.reply'
85
85
  # @notifications = @user.notifications.unopened_only.filtered_by_key('comment.reply')
86
86
  # @scope class
87
87
  # @param [String] key Key of the notification for filter
88
- # @return [ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] Database query of filtered notifications
88
+ # @return [ActiveRecord_AssociationRelation<Notification>, Mongoid::Criteria<Notification>] Database query of filtered notifications
89
89
  scope :filtered_by_key, ->(key) { where(key: key) }
90
90
 
91
91
  # Selects filtered notifications by notifiable_type, group or key with filter options.
92
- # @example Get filtered unopened notificatons of the @user for Comment notifiable class
92
+ # @example Get filtered unopened notification of the @user for Comment notifiable class
93
93
  # @notifications = @user.notifications.unopened_only.filtered_by_options({ filtered_by_type: 'Comment' })
94
- # @example Get filtered unopened notificatons of the @user for @article as group
94
+ # @example Get filtered unopened notification of the @user for @article as group
95
95
  # @notifications = @user.notifications.unopened_only.filtered_by_options({ filtered_by_group: @article })
96
- # @example Get filtered unopened notificatons of the @user for Article instance id=1 as group
96
+ # @example Get filtered unopened notification of the @user for Article instance id=1 as group
97
97
  # @notifications = @user.notifications.unopened_only.filtered_by_options({ filtered_by_group_type: 'Article', filtered_by_group_id: '1' })
98
- # @example Get filtered unopened notificatons of the @user with key 'comment.reply'
98
+ # @example Get filtered unopened notification of the @user with key 'comment.reply'
99
99
  # @notifications = @user.notifications.unopened_only.filtered_by_options({ filtered_by_key: 'comment.reply' })
100
- # @example Get filtered unopened notificatons of the @user for Comment notifiable class with key 'comment.reply'
100
+ # @example Get filtered unopened notification of the @user for Comment notifiable class with key 'comment.reply'
101
101
  # @notifications = @user.notifications.unopened_only.filtered_by_options({ filtered_by_type: 'Comment', filtered_by_key: 'comment.reply' })
102
- # @example Get custom filtered notificatons of the @user
102
+ # @example Get custom filtered notification of the @user
103
103
  # @notifications = @user.notifications.unopened_only.filtered_by_options({ custom_filter: ["created_at >= ?", time.hour.ago] })
104
104
  # @scope class
105
105
  # @param [Hash] options Options for filter
@@ -111,7 +111,7 @@ module ActivityNotification
111
111
  # @option options [String] :later_than (nil) ISO 8601 format time to filter notification index later than specified time
112
112
  # @option options [String] :earlier_than (nil) ISO 8601 format time to filter notification index earlier than specified time
113
113
  # @option options [Array|Hash] :custom_filter (nil) Custom notification filter (e.g. ["created_at >= ?", time.hour.ago] with ActiveRecord or {:created_at.gt => time.hour.ago} with Mongoid)
114
- # @return [ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] Database query of filtered notifications
114
+ # @return [ActiveRecord_AssociationRelation<Notification>, Mongoid::Criteria<Notification>] Database query of filtered notifications
115
115
  scope :filtered_by_options, ->(options = {}) {
116
116
  options = ActivityNotification.cast_to_indifferent_hash(options)
117
117
  filtered_notifications = all
@@ -141,22 +141,22 @@ module ActivityNotification
141
141
  }
142
142
 
143
143
  # Orders by latest (newest) first as created_at: :desc.
144
- # @return [ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] Database query of notifications ordered by latest first
144
+ # @return [ActiveRecord_AssociationRelation<Notification>, Mongoid::Criteria<Notification>] Database query of notifications ordered by latest first
145
145
  scope :latest_order, -> { order(created_at: :desc) }
146
146
 
147
147
  # Orders by earliest (older) first as created_at: :asc.
148
- # @return [ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] Database query of notifications ordered by earliest first
148
+ # @return [ActiveRecord_AssociationRelation<Notification>, Mongoid::Criteria<Notification>] Database query of notifications ordered by earliest first
149
149
  scope :earliest_order, -> { order(created_at: :asc) }
150
150
 
151
151
  # Orders by latest (newest) first as created_at: :desc.
152
152
  # This method is to be overridden in implementation for each ORM.
153
153
  # @param [Boolean] reverse If notifications will be ordered as earliest first
154
- # @return [ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] Database query of ordered notifications
154
+ # @return [ActiveRecord_AssociationRelation<Notification>, Mongoid::Criteria<Notification>] Database query of ordered notifications
155
155
  scope :latest_order!, ->(reverse = false) { reverse ? earliest_order : latest_order }
156
156
 
157
157
  # Orders by earliest (older) first as created_at: :asc.
158
158
  # This method is to be overridden in implementation for each ORM.
159
- # @return [ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] Database query of notifications ordered by earliest first
159
+ # @return [ActiveRecord_AssociationRelation<Notification>, Mongoid::Criteria<Notification>] Database query of notifications ordered by earliest first
160
160
  scope :earliest_order!, -> { earliest_order }
161
161
 
162
162
  # Returns latest notification instance.
@@ -224,13 +224,16 @@ module ActivityNotification
224
224
  # @option options [Boolean] :send_later (true) Whether it sends notification email asynchronously
225
225
  # @option options [Boolean] :publish_optional_targets (true) Whether it publishes notification to optional targets
226
226
  # @option options [Boolean] :pass_full_options (false) Whether it passes full options to notifiable.notification_targets, not a key only
227
- # @option options [Hash<String, Hash>] :optional_targets ({}) Options for optional targets, keys are optional target name (:amazon_sns or :slack etc) and values are options
228
- # @return [Array<Notificaion>] Array of generated notifications
227
+ # @option options [Hash<String, Hash>] :optional_targets ({}) Options for optional targets, keys are optional target name (:amazon_sns or :slack etc.) and values are options
228
+ # @return [Array<Notification>] Array of generated notifications
229
229
  def notify(target_type, notifiable, options = {})
230
230
  if options[:notify_later]
231
231
  notify_later(target_type, notifiable, options)
232
232
  else
233
233
  targets = notifiable.notification_targets(target_type, options[:pass_full_options] ? options : options[:key])
234
+ # Merge targets from instance-level subscriptions and deduplicate
235
+ instance_targets = notifiable.instance_subscription_targets(target_type, options[:key])
236
+ targets = merge_targets(targets, instance_targets)
234
237
  # Optimize blank check to avoid loading all records for ActiveRecord relations
235
238
  unless targets_empty?(targets)
236
239
  notify_all(targets, notifiable, options)
@@ -263,8 +266,8 @@ module ActivityNotification
263
266
  # @option options [Boolean] :send_later (true) Whether it sends notification email asynchronously
264
267
  # @option options [Boolean] :publish_optional_targets (true) Whether it publishes notification to optional targets
265
268
  # @option options [Boolean] :pass_full_options (false) Whether it passes full options to notifiable.notification_targets, not a key only
266
- # @option options [Hash<String, Hash>] :optional_targets ({}) Options for optional targets, keys are optional target name (:amazon_sns or :slack etc) and values are options
267
- # @return [Array<Notificaion>] Array of generated notifications
269
+ # @option options [Hash<String, Hash>] :optional_targets ({}) Options for optional targets, keys are optional target name (:amazon_sns or :slack etc.) and values are options
270
+ # @return [Array<Notification>] Array of generated notifications
268
271
  def notify_later(target_type, notifiable, options = {})
269
272
  target_type = target_type.to_s if target_type.is_a? Symbol
270
273
  options.delete(:notify_later)
@@ -296,8 +299,8 @@ module ActivityNotification
296
299
  # @option options [Boolean] :send_later (true) Whether it sends notification email asynchronously
297
300
  # @option options [Boolean] :publish_optional_targets (true) Whether it publishes notification to optional targets
298
301
  # @option options [Integer] :batch_size (1000) Batch size for ActiveRecord find_each (optional)
299
- # @option options [Hash<String, Hash>] :optional_targets ({}) Options for optional targets, keys are optional target name (:amazon_sns or :slack etc) and values are options
300
- # @return [Array<Notificaion>] Array of generated notifications
302
+ # @option options [Hash<String, Hash>] :optional_targets ({}) Options for optional targets, keys are optional target name (:amazon_sns or :slack etc.) and values are options
303
+ # @return [Array<Notification>] Array of generated notifications
301
304
  def notify_all(targets, notifiable, options = {})
302
305
  if options[:notify_later]
303
306
  notify_all_later(targets, notifiable, options)
@@ -331,8 +334,8 @@ module ActivityNotification
331
334
  # @option options [Boolean] :send_email (true) Whether it sends notification email
332
335
  # @option options [Boolean] :send_later (true) Whether it sends notification email asynchronously
333
336
  # @option options [Boolean] :publish_optional_targets (true) Whether it publishes notification to optional targets
334
- # @option options [Hash<String, Hash>] :optional_targets ({}) Options for optional targets, keys are optional target name (:amazon_sns or :slack etc) and values are options
335
- # @return [Array<Notificaion>] Array of generated notifications
337
+ # @option options [Hash<String, Hash>] :optional_targets ({}) Options for optional targets, keys are optional target name (:amazon_sns or :slack etc.) and values are options
338
+ # @return [Array<Notification>] Array of generated notifications
336
339
  def notify_all_later(targets, notifiable, options = {})
337
340
  options.delete(:notify_later)
338
341
  ActivityNotification::NotifyAllJob.perform_later(targets, notifiable, options)
@@ -341,7 +344,7 @@ module ActivityNotification
341
344
  # Generates notifications to one target.
342
345
  #
343
346
  # @example Notify to one user
344
- # ActivityNotification::Notification.notify_to @comment.auther, @comment
347
+ # ActivityNotification::Notification.notify_to @comment.author, @comment
345
348
  #
346
349
  # @param [Object] target Target to send notifications
347
350
  # @param [Object] notifiable Notifiable instance
@@ -355,7 +358,7 @@ module ActivityNotification
355
358
  # @option options [Boolean] :send_email (true) Whether it sends notification email
356
359
  # @option options [Boolean] :send_later (true) Whether it sends notification email asynchronously
357
360
  # @option options [Boolean] :publish_optional_targets (true) Whether it publishes notification to optional targets
358
- # @option options [Hash<String, Hash>] :optional_targets ({}) Options for optional targets, keys are optional target name (:amazon_sns or :slack etc) and values are options
361
+ # @option options [Hash<String, Hash>] :optional_targets ({}) Options for optional targets, keys are optional target name (:amazon_sns or :slack etc.) and values are options
359
362
  # @return [Notification] Generated notification instance
360
363
  def notify_to(target, notifiable, options = {})
361
364
  if options[:notify_later]
@@ -383,7 +386,7 @@ module ActivityNotification
383
386
  # Generates notifications to one target later by ActiveJob queue.
384
387
  #
385
388
  # @example Notify to one user later
386
- # ActivityNotification::Notification.notify_later_to @comment.auther, @comment
389
+ # ActivityNotification::Notification.notify_later_to @comment.author, @comment
387
390
  #
388
391
  # @param [Object] target Target to send notifications
389
392
  # @param [Object] notifiable Notifiable instance
@@ -396,7 +399,7 @@ module ActivityNotification
396
399
  # @option options [Boolean] :send_email (true) Whether it sends notification email
397
400
  # @option options [Boolean] :send_later (true) Whether it sends notification email asynchronously
398
401
  # @option options [Boolean] :publish_optional_targets (true) Whether it publishes notification to optional targets
399
- # @option options [Hash<String, Hash>] :optional_targets ({}) Options for optional targets, keys are optional target name (:amazon_sns or :slack etc) and values are options
402
+ # @option options [Hash<String, Hash>] :optional_targets ({}) Options for optional targets, keys are optional target name (:amazon_sns or :slack etc.) and values are options
400
403
  # @return [Notification] Generated notification instance
401
404
  def notify_later_to(target, notifiable, options = {})
402
405
  options.delete(:notify_later)
@@ -413,7 +416,7 @@ module ActivityNotification
413
416
  # @option options [Hash] :parameters ({}) Additional parameters of the notifications
414
417
  def generate_notification(target, notifiable, options = {})
415
418
  key = options[:key] || notifiable.default_notification_key
416
- if target.subscribes_to_notification?(key)
419
+ if target.subscribes_to_notification?(key, notifiable: notifiable)
417
420
  # Store notification
418
421
  notification = store_notification(target, notifiable, key, options)
419
422
  end
@@ -491,7 +494,7 @@ module ActivityNotification
491
494
  # Returns if group member of the notifications exists.
492
495
  # This method is designed to be called from controllers or views to avoid N+1.
493
496
  #
494
- # @param [Array<Notificaion>, ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] notifications Array or database query of the notifications to test member exists
497
+ # @param [Array<Notification>, ActiveRecord_AssociationRelation<Notification>, Mongoid::Criteria<Notification>] notifications Array or database query of the notifications to test member exists
495
498
  # @return [Boolean] If group member of the notifications exists
496
499
  def group_member_exists?(notifications)
497
500
  notifications.present? and group_members_of_owner_ids_only(notifications.map(&:id)).exists?
@@ -520,7 +523,7 @@ module ActivityNotification
520
523
 
521
524
  # Returns available options for kinds of notify methods.
522
525
  #
523
- # @return [Array<Notificaion>] Available options for kinds of notify methods
526
+ # @return [Array<Notification>] Available options for kinds of notify methods
524
527
  def available_options
525
528
  [:key, :group, :group_expiry_delay, :notifier, :parameters, :send_email, :send_later, :pass_full_options].freeze
526
529
  end
@@ -537,7 +540,7 @@ module ActivityNotification
537
540
  # @param [String] key Key of the notification
538
541
  # @param [Object] group Group unit of the notifications
539
542
  # @param [ActiveSupport::Duration] group_expiry_delay Expiry period of a notification group
540
- # @return [Notificaion] Valid group owner within the expiration period
543
+ # @return [Notification] Valid group owner within the expiration period
541
544
  def valid_group_owner(target, notifiable, key, group, group_expiry_delay)
542
545
  return nil if group.blank?
543
546
  # Bundle notification group by target, notifiable_type, group and key
@@ -581,6 +584,18 @@ module ActivityNotification
581
584
  end
582
585
  end
583
586
 
587
+ # Merges instance subscription targets with the main targets list, deduplicating.
588
+ # @api private
589
+ #
590
+ # @param [Object] targets Main targets collection (can be an ActiveRecord::Relation, Mongoid::Criteria, Array, etc.)
591
+ # @param [Array] instance_targets Targets from instance-level subscriptions
592
+ # @return [Array] Deduplicated array of all targets
593
+ def merge_targets(targets, instance_targets)
594
+ return targets if instance_targets.blank?
595
+ all_targets = targets.respond_to?(:to_a) ? targets.to_a : Array(targets)
596
+ (all_targets + instance_targets).uniq
597
+ end
598
+
584
599
  # Processes targets in batches for memory efficiency with large collections
585
600
  # @api private
586
601
  #
@@ -783,7 +798,7 @@ module ActivityNotification
783
798
  # Returns the latest group member notification instance of this notification.
784
799
  # If this group owner has no group members, group owner instance self will be returned.
785
800
  #
786
- # @return [Notificaion] Notification instance of the latest group member notification
801
+ # @return [Notification] Notification instance of the latest group member notification
787
802
  def latest_group_member
788
803
  notification = group_member? && group_owner.present? ? group_owner : self
789
804
  notification.group_member_exists? ? notification.group_members.latest : self
@@ -791,7 +806,7 @@ module ActivityNotification
791
806
 
792
807
  # Remove from notification group and make a new group owner.
793
808
  #
794
- # @return [Notificaion] New group owner instance of the notification group
809
+ # @return [Notification] New group owner instance of the notification group
795
810
  def remove_from_group
796
811
  new_group_owner = group_members.earliest
797
812
  if new_group_owner.present?
@@ -11,7 +11,7 @@ module ActivityNotification
11
11
  # @subscriptions = @user.subscriptions.filtered_by_key('comment.reply')
12
12
  # @scope class
13
13
  # @param [String] key Key of the subscription for filter
14
- # @return [ActiveRecord_AssociationRelation<Subscription>, Mongoid::Criteria<Notificaion>] Database query of filtered subscriptions
14
+ # @return [ActiveRecord_AssociationRelation<Subscription>, Mongoid::Criteria<Notification>] Database query of filtered subscriptions
15
15
  scope :filtered_by_key, ->(key) { where(key: key) }
16
16
 
17
17
  # Selects filtered subscriptions by key with filter options.
@@ -23,7 +23,7 @@ module ActivityNotification
23
23
  # @param [Hash] options Options for filter
24
24
  # @option options [String] :filtered_by_key (nil) Key of the subscription for filter
25
25
  # @option options [Array|Hash] :custom_filter (nil) Custom subscription filter (e.g. ["created_at >= ?", time.hour.ago] or ['created_at.gt': time.hour.ago])
26
- # @return [ActiveRecord_AssociationRelation<Subscription>, Mongoid::Criteria<Notificaion>] Database query of filtered subscriptions
26
+ # @return [ActiveRecord_AssociationRelation<Subscription>, Mongoid::Criteria<Notification>] Database query of filtered subscriptions
27
27
  scope :filtered_by_options, ->(options = {}) {
28
28
  options = ActivityNotification.cast_to_indifferent_hash(options)
29
29
  filtered_subscriptions = all
@@ -37,34 +37,34 @@ module ActivityNotification
37
37
  }
38
38
 
39
39
  # Orders by latest (newest) first as created_at: :desc.
40
- # @return [ActiveRecord_AssociationRelation<Subscription>, Mongoid::Criteria<Notificaion>] Database query of subscriptions ordered by latest first
40
+ # @return [ActiveRecord_AssociationRelation<Subscription>, Mongoid::Criteria<Notification>] Database query of subscriptions ordered by latest first
41
41
  scope :latest_order, -> { order(created_at: :desc) }
42
42
 
43
43
  # Orders by earliest (older) first as created_at: :asc.
44
- # @return [ActiveRecord_AssociationRelation<Subscription>, Mongoid::Criteria<Notificaion>] Database query of subscriptions ordered by earliest first
44
+ # @return [ActiveRecord_AssociationRelation<Subscription>, Mongoid::Criteria<Notification>] Database query of subscriptions ordered by earliest first
45
45
  scope :earliest_order, -> { order(created_at: :asc) }
46
46
 
47
47
  # Orders by latest (newest) first as created_at: :desc.
48
48
  # This method is to be overridden in implementation for each ORM.
49
49
  # @param [Boolean] reverse If subscriptions will be ordered as earliest first
50
- # @return [ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] Database query of ordered subscriptions
50
+ # @return [ActiveRecord_AssociationRelation<Notification>, Mongoid::Criteria<Notification>] Database query of ordered subscriptions
51
51
  scope :latest_order!, ->(reverse = false) { reverse ? earliest_order : latest_order }
52
52
 
53
53
  # Orders by earliest (older) first as created_at: :asc.
54
54
  # This method is to be overridden in implementation for each ORM.
55
- # @return [ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] Database query of subscriptions ordered by earliest first
55
+ # @return [ActiveRecord_AssociationRelation<Notification>, Mongoid::Criteria<Notification>] Database query of subscriptions ordered by earliest first
56
56
  scope :earliest_order!, -> { earliest_order }
57
57
 
58
58
  # Orders by latest (newest) first as subscribed_at: :desc.
59
- # @return [ActiveRecord_AssociationRelation<Subscription>, Mongoid::Criteria<Notificaion>] Database query of subscriptions ordered by latest subscribed_at first
59
+ # @return [ActiveRecord_AssociationRelation<Subscription>, Mongoid::Criteria<Notification>] Database query of subscriptions ordered by latest subscribed_at first
60
60
  scope :latest_subscribed_order, -> { order(subscribed_at: :desc) }
61
61
 
62
62
  # Orders by earliest (older) first as subscribed_at: :asc.
63
- # @return [ActiveRecord_AssociationRelation<Subscription>, Mongoid::Criteria<Notificaion>] Database query of subscriptions ordered by earliest subscribed_at first
63
+ # @return [ActiveRecord_AssociationRelation<Subscription>, Mongoid::Criteria<Notification>] Database query of subscriptions ordered by earliest subscribed_at first
64
64
  scope :earliest_subscribed_order, -> { order(subscribed_at: :asc) }
65
65
 
66
66
  # Orders by key name as key: :asc.
67
- # @return [ActiveRecord_AssociationRelation<Subscription>, Mongoid::Criteria<Notificaion>] Database query of subscriptions ordered by key name
67
+ # @return [ActiveRecord_AssociationRelation<Subscription>, Mongoid::Criteria<Notification>] Database query of subscriptions ordered by key name
68
68
  scope :key_order, -> { order(key: :asc) }
69
69
 
70
70
  # Convert Time value to store in database as Hash value.
@@ -182,7 +182,7 @@ module ActivityNotification
182
182
  # Returns if the target subscribes to the specified optional target.
183
183
  #
184
184
  # @param [Symbol] optional_target_name Symbol class name of the optional target implementation (e.g. :amazon_sns, :slack)
185
- # @param [Boolean] subscribe_as_default Default subscription value to use when the subscription record does not configured
185
+ # @param [Boolean] subscribe_as_default Default subscription value to use when the subscription record is not configured
186
186
  # @return [Boolean] If the target subscribes to the specified optional target
187
187
  def subscribing_to_optional_target?(optional_target_name, subscribe_as_default = ActivityNotification.config.subscribe_to_optional_targets_as_default)
188
188
  optional_target_key = Subscription.to_optional_target_key(optional_target_name)
@@ -105,7 +105,7 @@ module ActivityNotification
105
105
  end
106
106
  end
107
107
 
108
- # Convets to class name.
108
+ # Converts to class name.
109
109
  # This function returns base_class name for STI models if the class responds to base_class method.
110
110
  # @see https://github.com/simukappu/activity_notification/issues/89
111
111
  # @see https://github.com/simukappu/activity_notification/pull/139
@@ -114,26 +114,26 @@ module ActivityNotification
114
114
  self.class.respond_to?(:base_class) ? self.class.base_class.name : self.class.name
115
115
  end
116
116
 
117
- # Convets to singularized model name (resource name).
117
+ # Converts to singularized model name (resource name).
118
118
  # @return [String] Singularized model name (resource name)
119
119
  def to_resource_name
120
120
  self.to_class_name.demodulize.singularize.underscore
121
121
  end
122
122
 
123
- # Convets to pluralized model name (resources name).
123
+ # Converts to pluralized model name (resources name).
124
124
  # @return [String] Pluralized model name (resources name)
125
125
  def to_resources_name
126
126
  self.to_class_name.demodulize.pluralize.underscore
127
127
  end
128
128
 
129
- # Convets to printable model type name to be humanized.
129
+ # Converts to printable model type name to be humanized.
130
130
  # @return [String] Printable model type name
131
131
  # @todo Is this the best to make readable?
132
132
  def printable_type
133
133
  "#{self.to_class_name.demodulize.humanize}"
134
134
  end
135
135
 
136
- # Convets to printable model name to show in view or email.
136
+ # Converts to printable model name to show in view or email.
137
137
  # @return [String] Printable model name
138
138
  def printable_name
139
139
  "#{self.printable_type} (#{id})"
@@ -91,6 +91,15 @@ module ActivityNotification
91
91
  # @return [String, Array<String>, Proc] CC email address(es) for notification email.
92
92
  attr_accessor :mailer_cc
93
93
 
94
+ # @overload mailer_attachments
95
+ # Returns attachment specification(s) for notification emails
96
+ # @return [Hash, Array<Hash>, Proc, nil] Attachment specification(s) for notification emails.
97
+ # @overload mailer_attachments=(value)
98
+ # Sets attachment specification(s) for notification emails
99
+ # @param [Hash, Array<Hash>, Proc, nil] mailer_attachments The new mailer_attachments
100
+ # @return [Hash, Array<Hash>, Proc, nil] Attachment specification(s) for notification emails.
101
+ attr_accessor :mailer_attachments
102
+
94
103
  # @overload mailer
95
104
  # Returns mailer class for email notification
96
105
  # @return [String] Mailer class for email notification.
@@ -173,8 +182,8 @@ module ActivityNotification
173
182
  attr_accessor :composite_key_delimiter
174
183
 
175
184
  # @overload store_with_associated_records
176
- # Returns whether activity_notification stores notificaion records including associated records like target and notifiable
177
- # @return [Boolean] Whether activity_notification stores notificaion records including associated records like target and notifiable.
185
+ # Returns whether activity_notification stores notification records including associated records like target and notifiable
186
+ # @return [Boolean] Whether activity_notification stores Notification records including associated records like target and notifiable.
178
187
  attr_reader :store_with_associated_records
179
188
 
180
189
  # @overload action_cable_enabled
@@ -246,6 +255,7 @@ module ActivityNotification
246
255
  @subscribe_to_optional_targets_as_default = nil
247
256
  @mailer_sender = nil
248
257
  @mailer_cc = nil
258
+ @mailer_attachments = nil
249
259
  @mailer = 'ActivityNotification::Mailer'
250
260
  @parent_mailer = 'ActionMailer::Base'
251
261
  @parent_job = 'ActiveJob::Base'
@@ -271,10 +281,10 @@ module ActivityNotification
271
281
  @orm = orm.to_sym
272
282
  end
273
283
 
274
- # Sets whether activity_notification stores notificaion records including associated records like target and notifiable.
284
+ # Sets whether activity_notification stores notification records including associated records like target and notifiable.
275
285
  # This store_with_associated_records option can be set true only when you use mongoid or dynamoid ORM.
276
286
  # @param [Boolean] store_with_associated_records The new store_with_associated_records
277
- # @return [Boolean] Whether activity_notification stores notificaion records including associated records like target and notifiable.
287
+ # @return [Boolean] Whether activity_notification stores notification records including associated records like target and notifiable.
278
288
  def store_with_associated_records=(store_with_associated_records)
279
289
  if store_with_associated_records && [:mongoid, :dynamoid].exclude?(@orm) then raise ActivityNotification::ConfigError, "config.store_with_associated_records can be set true only when you use mongoid or dynamoid ORM." end
280
290
  @store_with_associated_records = store_with_associated_records
@@ -289,7 +299,7 @@ module ActivityNotification
289
299
  end
290
300
 
291
301
  # Returns default optional target subscription value to use when the subscription record does not configured
292
- # @return [Boolean] Default optinal target subscription value to use when the subscription record does not configured.
302
+ # @return [Boolean] Default optional target subscription value to use when the subscription record does not configured.
293
303
  def subscribe_to_optional_targets_as_default
294
304
  return false unless @subscribe_as_default
295
305
 
@@ -67,14 +67,12 @@ module ActivityNotification
67
67
  end
68
68
 
69
69
  # Returns path of the target view templates.
70
- # Do not make this method public unless Rendarable module calls controller's target_view_path method to render resources.
70
+ # Do not make this method public unless Renderable module calls controller's target_view_path method to render resources.
71
71
  # @api protected
72
72
  def target_view_path
73
73
  target_type = @target.to_resources_name
74
74
  view_path = [controller_path, target_type].join('/')
75
- lookup_context.exists?(action_name, view_path) ?
76
- view_path :
77
- [controller_path, DEFAULT_VIEW_DIRECTORY].join('/')
75
+ lookup_context.exists?(action_name, view_path) ? view_path : [controller_path, DEFAULT_VIEW_DIRECTORY].join('/')
78
76
  end
79
77
 
80
78
  # Sets view prefixes for target view path.
@@ -14,7 +14,7 @@ module ActivityNotification
14
14
  # Authenticate devise resource by Devise (e.g. calling authenticate_user! method).
15
15
  # @api protected
16
16
  # @todo Needs to call authenticate method by more secure way
17
- # @return [Response] Redirects for unsigned in target by Devise, returns HTTP 403 without neccesary target method or returns 400 when request parameters are not enough
17
+ # @return [Response] Redirects for unsigned in target by Devise, returns HTTP 403 without necessary target method or returns 400 when request parameters are not enough
18
18
  def authenticate_devise_resource!
19
19
  if params[:devise_type].present?
20
20
  authenticate_method_name = "authenticate_#{params[:devise_type].to_resource_name}!"
@@ -29,7 +29,7 @@ module ActivityNotification
29
29
  end
30
30
 
31
31
  # Sets @target instance variable from request parameters.
32
- # This method override super (ActivityNotiication::CommonController#set_target)
32
+ # This method override super (ActivityNotification::CommonController#set_target)
33
33
  # to set devise authenticated target when the target_id params is not specified.
34
34
  # @api protected
35
35
  # @return [Object] Target instance (Returns HTTP 400 when request parameters are not enough)
@@ -5,35 +5,35 @@ module ActivityNotification
5
5
 
6
6
  included do
7
7
  class ::String
8
- # Convets to model instance.
8
+ # Converts to model instance.
9
9
  # @return [Object] Model instance
10
10
  def to_model_name
11
11
  singularize.camelize
12
12
  end
13
13
 
14
- # Convets to model class.
14
+ # Converts to model class.
15
15
  # @return [Class] Model class
16
16
  def to_model_class
17
17
  to_model_name.classify.constantize
18
18
  end
19
19
 
20
- # Convets to singularized model name (resource name).
20
+ # Converts to singularized model name (resource name).
21
21
  # @return [String] Singularized model name (resource name)
22
22
  def to_resource_name
23
23
  singularize.underscore
24
24
  end
25
25
 
26
- # Convets to pluralized model name (resources name).
26
+ # Converts to pluralized model name (resources name).
27
27
  # @return [String] Pluralized model name (resources name)
28
28
  def to_resources_name
29
29
  pluralize.underscore
30
30
  end
31
31
 
32
- # Convets to boolean.
32
+ # Converts to boolean.
33
33
  # Returns true for 'true', '1', 'yes', 'on' and 't'.
34
34
  # Returns false for 'false', '0', 'no', 'off' and 'f'.
35
35
  # @param [Boolean] default Default value to return when the String is not interpretable
36
- # @return [Boolean] Convered boolean value
36
+ # @return [Boolean] Converted boolean value
37
37
  def to_boolean(default = nil)
38
38
  return true if ['true', '1', 'yes', 'on', 't'].include? self
39
39
  return false if ['false', '0', 'no', 'off', 'f'].include? self
@@ -2,10 +2,10 @@ module ActivityNotification
2
2
  # Provides a shortcut from views to the rendering method.
3
3
  # Module extending ActionView::Base and adding `render_notification` helper.
4
4
  module ViewHelpers
5
- # View helper for rendering an notification, calls {Notification#render} internally.
5
+ # View helper for rendering a notification, calls {Notification#render} internally.
6
6
  # @see Notification#render
7
7
  #
8
- # @param [Notification, Array<Notificaion>] notifications Array or single instance of notifications to render
8
+ # @param [Notification, Array<Notification>] notifications Array or single instance of notifications to render
9
9
  # @param [Hash] options Options for rendering notifications
10
10
  # @option options [String, Symbol] :target (nil) Target type name to find template or i18n text
11
11
  # @option options [String] :partial ("activity_notification/notifications/#{target}", controller.target_view_path, 'activity_notification/notifications/default') Partial template name
@@ -489,7 +489,7 @@ module ActivityNotification
489
489
  # @api private
490
490
  #
491
491
  # @param [Object] target Notification target instance
492
- # @param [Array<Notificaion>] notification_index Array notification index
492
+ # @param [Array<Notification>] notification_index Array notification index
493
493
  # @param [Hash] params Option parameter to send render_notification
494
494
  def prepare_content_for(target, notification_index, params)
495
495
  content_for :notification_index do