activity_notification 0.0.10 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +6 -0
  3. data/Gemfile +6 -3
  4. data/Gemfile.lock +74 -58
  5. data/README.md +53 -26
  6. data/activity_notification.gemspec +2 -0
  7. data/app/controllers/activity_notification/notifications_controller.rb +4 -4
  8. data/app/mailers/activity_notification/mailer.rb +9 -3
  9. data/app/views/activity_notification/mailer/default/default.html.erb +9 -4
  10. data/app/views/activity_notification/mailer/default/default.text.erb +10 -0
  11. data/app/views/activity_notification/notifications/default/_default.html.erb +173 -34
  12. data/app/views/activity_notification/notifications/default/_index.html.erb +119 -11
  13. data/app/views/activity_notification/notifications/default/destroy.js.erb +2 -2
  14. data/app/views/activity_notification/notifications/default/index.html.erb +25 -14
  15. data/app/views/activity_notification/notifications/default/open.js.erb +2 -2
  16. data/app/views/activity_notification/notifications/default/open_all.js.erb +2 -2
  17. data/app/views/activity_notification/notifications/default/show.html.erb +1 -1
  18. data/gemfiles/Gemfile.rails-4.2 +0 -2
  19. data/gemfiles/Gemfile.rails-4.2.lock +3 -3
  20. data/gemfiles/Gemfile.rails-5.0 +1 -3
  21. data/lib/activity_notification.rb +10 -9
  22. data/lib/activity_notification/apis/notification_api.rb +108 -14
  23. data/lib/activity_notification/common.rb +11 -2
  24. data/lib/activity_notification/config.rb +13 -13
  25. data/lib/activity_notification/helpers/view_helpers.rb +26 -4
  26. data/lib/activity_notification/mailers/helpers.rb +8 -4
  27. data/lib/activity_notification/models.rb +4 -0
  28. data/lib/activity_notification/models/concerns/group.rb +32 -0
  29. data/lib/activity_notification/models/concerns/notifiable.rb +60 -32
  30. data/lib/activity_notification/models/concerns/notifier.rb +17 -1
  31. data/lib/activity_notification/models/concerns/target.rb +114 -55
  32. data/lib/activity_notification/models/notification.rb +26 -25
  33. data/lib/activity_notification/rails.rb +1 -0
  34. data/lib/activity_notification/renderable.rb +8 -3
  35. data/lib/activity_notification/roles/acts_as_common.rb +28 -0
  36. data/lib/activity_notification/roles/acts_as_group.rb +38 -0
  37. data/lib/activity_notification/roles/acts_as_notifiable.rb +56 -22
  38. data/lib/activity_notification/roles/acts_as_notifier.rb +25 -2
  39. data/lib/activity_notification/roles/acts_as_target.rb +27 -9
  40. data/lib/activity_notification/version.rb +1 -1
  41. data/lib/generators/templates/activity_notification.rb +1 -1
  42. data/spec/concerns/apis/notification_api_spec.rb +361 -2
  43. data/spec/concerns/common_spec.rb +36 -0
  44. data/spec/concerns/models/group_spec.rb +61 -0
  45. data/spec/concerns/models/notifiable_spec.rb +37 -0
  46. data/spec/concerns/models/notifier_spec.rb +48 -0
  47. data/spec/concerns/models/target_spec.rb +81 -31
  48. data/spec/factories/dummy/dummy_group.rb +4 -0
  49. data/spec/helpers/view_helpers_spec.rb +13 -0
  50. data/spec/mailers/mailer_spec.rb +8 -1
  51. data/spec/models/dummy/dummy_group_spec.rb +6 -0
  52. data/spec/rails_app/app/assets/stylesheets/application.css +15 -0
  53. data/spec/rails_app/app/assets/stylesheets/reset.css +85 -0
  54. data/spec/rails_app/app/assets/stylesheets/style.css +244 -0
  55. data/spec/rails_app/app/controllers/articles_controller.rb +1 -1
  56. data/spec/rails_app/app/models/admin.rb +2 -1
  57. data/spec/rails_app/app/models/article.rb +9 -2
  58. data/spec/rails_app/app/models/comment.rb +8 -2
  59. data/spec/rails_app/app/models/dummy/dummy_group.rb +4 -0
  60. data/spec/rails_app/app/models/user.rb +8 -3
  61. data/spec/rails_app/app/views/articles/_form.html.erb +14 -10
  62. data/spec/rails_app/app/views/articles/edit.html.erb +8 -6
  63. data/spec/rails_app/app/views/articles/index.html.erb +59 -67
  64. data/spec/rails_app/app/views/articles/new.html.erb +7 -5
  65. data/spec/rails_app/app/views/articles/show.html.erb +47 -36
  66. data/spec/rails_app/app/views/layouts/_header.html.erb +36 -9
  67. data/spec/rails_app/app/views/layouts/application.html.erb +8 -6
  68. data/spec/rails_app/config/environments/development.rb +9 -0
  69. data/spec/rails_app/config/initializers/activity_notification.rb +1 -1
  70. data/spec/rails_app/db/schema.rb +14 -20
  71. data/spec/rails_app/db/seeds.rb +5 -5
  72. data/spec/rails_app/lib/mailer_previews/mailer_preview.rb +13 -0
  73. data/spec/roles/acts_as_group_spec.rb +32 -0
  74. data/spec/roles/acts_as_notifiable_spec.rb +1 -1
  75. data/spec/roles/acts_as_notifier_spec.rb +15 -0
  76. data/spec/roles/acts_as_target_spec.rb +1 -1
  77. metadata +52 -2
@@ -1,14 +1,18 @@
1
+ require 'activity_notification/roles/acts_as_common'
1
2
  require 'activity_notification/roles/acts_as_target'
2
3
  require 'activity_notification/roles/acts_as_notifiable'
3
4
  require 'activity_notification/roles/acts_as_notifier'
5
+ require 'activity_notification/roles/acts_as_group'
4
6
 
5
7
  module ActivityNotification
6
8
  module Models
7
9
  extend ActiveSupport::Concern
8
10
  included do
11
+ include ActivityNotification::ActsAsCommon
9
12
  include ActivityNotification::ActsAsTarget
10
13
  include ActivityNotification::ActsAsNotifiable
11
14
  include ActivityNotification::ActsAsNotifier
15
+ include ActivityNotification::ActsAsGroup
12
16
  end
13
17
  end
14
18
  end
@@ -0,0 +1,32 @@
1
+ module ActivityNotification
2
+ # Notification group implementation included in group model to bundle notification.
3
+ module Group
4
+ extend ActiveSupport::Concern
5
+ included do
6
+ include Common
7
+ class_attribute :_printable_notification_group_name
8
+ set_group_class_defaults
9
+ end
10
+
11
+ class_methods do
12
+ # Checks if the model includes notification group methods are available.
13
+ # @return [Boolean] Always true
14
+ def available_as_group?
15
+ true
16
+ end
17
+
18
+ # Sets default values to group class fields.
19
+ # @return [NilClass] nil
20
+ def set_group_class_defaults
21
+ self._printable_notification_group_name = :printable_name
22
+ nil
23
+ end
24
+ end
25
+
26
+ # Returns printable group model name to show in view or email.
27
+ # @return [String] Printable group model name
28
+ def printable_group_name
29
+ resolve_value(_printable_notification_group_name)
30
+ end
31
+ end
32
+ end
@@ -9,21 +9,31 @@ module ActivityNotification
9
9
  include Common
10
10
  include ActionDispatch::Routing::PolymorphicRoutes
11
11
  include Rails.application.routes.url_helpers
12
+
13
+ # Has many notification instances for this notifiable.
14
+ # Dependency for these notifications can be overriden from acts_as_notifiable.
15
+ # @scope instance
16
+ # @return [Array<Notificaion>] Array or database query of notifications for this notifiable
17
+ has_many :generated_notifications_as_notifiable,
18
+ class_name: "::ActivityNotification::Notification",
19
+ as: :notifiable
20
+
12
21
  class_attribute :_notification_targets,
13
22
  :_notification_group,
14
23
  :_notifier,
15
24
  :_notification_parameters,
16
25
  :_notification_email_allowed,
17
- :_notifiable_path
26
+ :_notifiable_path,
27
+ :_printable_notifiable_name
18
28
  set_notifiable_class_defaults
19
29
  end
20
-
30
+
21
31
  # Returns default_url_options for polymorphic_path.
22
32
  # @return [Hash] Rails.application.routes.default_url_options
23
33
  def default_url_options
24
34
  Rails.application.routes.default_url_options
25
35
  end
26
-
36
+
27
37
  class_methods do
28
38
  # Checks if the model includes notifiable and notifiable methods are available.
29
39
  # @return [Boolean] Always true
@@ -32,7 +42,7 @@ module ActivityNotification
32
42
  end
33
43
 
34
44
  # Sets default values to notifiable class fields.
35
- # @return [Nil] nil
45
+ # @return [NilClass] nil
36
46
  def set_notifiable_class_defaults
37
47
  self._notification_targets = {}
38
48
  self._notification_group = {}
@@ -40,6 +50,7 @@ module ActivityNotification
40
50
  self._notification_parameters = {}
41
51
  self._notification_email_allowed = {}
42
52
  self._notifiable_path = {}
53
+ self._printable_notifiable_name = {}
43
54
  nil
44
55
  end
45
56
  end
@@ -50,13 +61,12 @@ module ActivityNotification
50
61
  # @param [String] target_type Target type to notify
51
62
  # @param [String] key Key of the notification
52
63
  # @return [Array<Notificaion> | ActiveRecord_AssociationRelation<Notificaion>] Array or database query of the notification targets
53
- def notification_targets(target_type, key)
54
- target_typed_method_name = "notification_#{target_type.to_s.to_resources_name}"
64
+ def notification_targets(target_type, key = nil)
65
+ target_typed_method_name = "notification_#{cast_to_resources_name(target_type)}"
55
66
  resolved_parameter = resolve_parameter(
56
67
  target_typed_method_name,
57
- _notification_targets[target_type.to_s.to_resources_name.to_sym],
58
- nil,
59
- key)
68
+ _notification_targets[cast_to_resources_sym(target_type)],
69
+ nil, key)
60
70
  unless resolved_parameter
61
71
  raise NotImplementedError, "You have to implement #{self.class}##{target_typed_method_name} "\
62
72
  "or set :targets in acts_as_notifiable"
@@ -70,12 +80,11 @@ module ActivityNotification
70
80
  # @param [String] target_type Target type to notify
71
81
  # @param [String] key Key of the notification
72
82
  # @return [Object] Group owner of the notification
73
- def notification_group(target_type, key)
83
+ def notification_group(target_type, key = nil)
74
84
  resolve_parameter(
75
- "notification_group_for_#{target_type.to_s.to_resources_name}",
76
- _notification_group[target_type.to_s.to_resources_name.to_sym],
77
- nil,
78
- key)
85
+ "notification_group_for_#{cast_to_resources_name(target_type)}",
86
+ _notification_group[cast_to_resources_sym(target_type)],
87
+ nil, key)
79
88
  end
80
89
 
81
90
  # Returns additional notification parameters from configured field or overriden method.
@@ -84,12 +93,11 @@ module ActivityNotification
84
93
  # @param [String] target_type Target type to notify
85
94
  # @param [String] key Key of the notification
86
95
  # @return [Hash] Additional notification parameters
87
- def notification_parameters(target_type, key)
96
+ def notification_parameters(target_type, key = nil)
88
97
  resolve_parameter(
89
- "notification_parameters_for_#{target_type.to_s.to_resources_name}",
90
- _notification_parameters[target_type.to_s.to_resources_name.to_sym],
91
- {},
92
- key)
98
+ "notification_parameters_for_#{cast_to_resources_name(target_type)}",
99
+ _notification_parameters[cast_to_resources_sym(target_type)],
100
+ {}, key)
93
101
  end
94
102
 
95
103
  # Returns notifier of the notification from configured field or overriden method.
@@ -98,12 +106,11 @@ module ActivityNotification
98
106
  # @param [String] target_type Target type to notify
99
107
  # @param [String] key Key of the notification
100
108
  # @return [Object] Notifier of the notification
101
- def notifier(target_type, key)
109
+ def notifier(target_type, key = nil)
102
110
  resolve_parameter(
103
- "notifier_for_#{target_type.to_s.to_resources_name}",
104
- _notifier[target_type.to_s.to_resources_name.to_sym],
105
- nil,
106
- key)
111
+ "notifier_for_#{cast_to_resources_name(target_type)}",
112
+ _notifier[cast_to_resources_sym(target_type)],
113
+ nil, key)
107
114
  end
108
115
 
109
116
  # Returns if sending notification email is allowed for the notifiable from configured field or overriden method.
@@ -112,10 +119,10 @@ module ActivityNotification
112
119
  # @param [Object] target Target instance to notify
113
120
  # @param [String] key Key of the notification
114
121
  # @return [Boolean] If sending notification email is allowed for the notifiable
115
- def notification_email_allowed?(target, key)
122
+ def notification_email_allowed?(target, key = nil)
116
123
  resolve_parameter(
117
- "notification_email_allowed_for_#{target.class.to_s.to_resources_name}?",
118
- _notification_email_allowed[target.class.to_s.to_resources_name.to_sym],
124
+ "notification_email_allowed_for_#{cast_to_resources_name(target.class)}?",
125
+ _notification_email_allowed[cast_to_resources_sym(target.class)],
119
126
  ActivityNotification.config.email_enabled,
120
127
  target, key)
121
128
  end
@@ -126,12 +133,11 @@ module ActivityNotification
126
133
  # @param [String] target_type Target type to notify
127
134
  # @param [String] key Key of the notification
128
135
  # @return [String] Notifiable path URL to move after opening notification
129
- def notifiable_path(target_type, key)
136
+ def notifiable_path(target_type, key = nil)
130
137
  resolved_parameter = resolve_parameter(
131
- "notifiable_path_for_#{target_type.to_s.to_resources_name}",
132
- _notifiable_path[target_type.to_s.to_resources_name.to_sym],
133
- nil,
134
- key)
138
+ "notifiable_path_for_#{cast_to_resources_name(target_type)}",
139
+ _notifiable_path[cast_to_resources_sym(target_type)],
140
+ nil, key)
135
141
  unless resolved_parameter
136
142
  begin
137
143
  resolved_parameter = polymorphic_path(self)
@@ -144,6 +150,16 @@ module ActivityNotification
144
150
  resolved_parameter
145
151
  end
146
152
 
153
+ # Returns printable notifiable model name to show in view or email.
154
+ # @return [String] Printable notifiable model name
155
+ def printable_notifiable_name(target, key = nil)
156
+ resolve_parameter(
157
+ "printable_notifiable_name_for_#{cast_to_resources_name(target.class)}?",
158
+ _printable_notifiable_name[cast_to_resources_sym(target.class)],
159
+ printable_name,
160
+ target, key)
161
+ end
162
+
147
163
  # overriding_notification_email_key is the method to override key definition for Mailer
148
164
  # When respond_to?(overriding_notification_email_key) returns true,
149
165
  # Mailer uses overriding_notification_email_key instead of original key.
@@ -230,5 +246,17 @@ module ActivityNotification
230
246
  default_value
231
247
  end
232
248
  end
249
+
250
+ # Casts to resources name.
251
+ # @api private
252
+ def cast_to_resources_name(target_type)
253
+ target_type.to_s.to_resources_name
254
+ end
255
+
256
+ # Casts to symbol of resources name.
257
+ # @api private
258
+ def cast_to_resources_sym(target_type)
259
+ target_type.to_s.to_resources_name.to_sym
260
+ end
233
261
  end
234
262
  end
@@ -1,4 +1,5 @@
1
1
  module ActivityNotification
2
+ # Notifier implementation included in notifier model to be notified, like users or administrators.
2
3
  module Notifier
3
4
  extend ActiveSupport::Concern
4
5
  included do
@@ -6,14 +7,29 @@ module ActivityNotification
6
7
  has_many :sent_notifications,
7
8
  class_name: "::ActivityNotification::Notification",
8
9
  as: :notifier
10
+ class_attribute :_printable_notifier_name
11
+ set_notifier_class_defaults
9
12
  end
10
13
 
11
14
  class_methods do
12
- # Checks if the model includes notifier and notifier methods are available.
15
+ # Checks if the model includes notifier methods are available.
13
16
  # @return [Boolean] Always true
14
17
  def available_as_notifier?
15
18
  true
16
19
  end
20
+
21
+ # Sets default values to notifier class fields.
22
+ # @return [NilClass] nil
23
+ def set_notifier_class_defaults
24
+ self._printable_notifier_name = :printable_name
25
+ nil
26
+ end
27
+ end
28
+
29
+ # Returns printable notifier model name to show in view or email.
30
+ # @return [String] Printable notifier model name
31
+ def printable_notifier_name
32
+ resolve_value(_printable_notifier_name)
17
33
  end
18
34
  end
19
35
  end
@@ -10,9 +10,13 @@ module ActivityNotification
10
10
  # @return [Array<Notificaion>] Array or database query of notifications of this target
11
11
  has_many :notifications,
12
12
  class_name: "::ActivityNotification::Notification",
13
- as: :target
13
+ as: :target,
14
+ dependent: :delete_all
14
15
 
15
- class_attribute :_notification_email, :_notification_email_allowed, :_notification_devise_resource
16
+ class_attribute :_notification_email,
17
+ :_notification_email_allowed,
18
+ :_notification_devise_resource,
19
+ :_printable_notification_target_name
16
20
  set_target_class_defaults
17
21
  end
18
22
 
@@ -24,11 +28,12 @@ module ActivityNotification
24
28
  end
25
29
 
26
30
  # Sets default values to target class fields.
27
- # @return [Nil] nil
31
+ # @return [NilClass] nil
28
32
  def set_target_class_defaults
29
- self._notification_email = nil
30
- self._notification_email_allowed = ActivityNotification.config.email_enabled
31
- self._notification_devise_resource = ->(model) { model }
33
+ self._notification_email = nil
34
+ self._notification_email_allowed = ActivityNotification.config.email_enabled
35
+ self._notification_devise_resource = ->(model) { model }
36
+ self._printable_notification_target_name = :printable_name
32
37
  nil
33
38
  end
34
39
  end
@@ -58,48 +63,58 @@ module ActivityNotification
58
63
  # @return [Boolean] If current resource signed in with Devise is authenticated for the notification
59
64
  def authenticated_with_devise?(current_resource)
60
65
  devise_resource = resolve_value(_notification_devise_resource)
61
- unless current_resource.instance_of? devise_resource.class
66
+ unless current_resource.blank? or current_resource.instance_of? devise_resource.class
62
67
  raise TypeError,
63
68
  "Defferent type of current resource #{current_resource.class} "\
64
69
  "with devise resource #{devise_resource.class} has been passed to #{self.class}##{__method__}. "\
65
70
  "You have to override #{self.class}##{__method__} method or set devise_resource in acts_as_target."
66
71
  end
67
- current_resource == devise_resource
72
+ current_resource.present? and current_resource == devise_resource
73
+ end
74
+
75
+ # Returns printable target model name to show in view or email.
76
+ # @return [String] Printable target model name
77
+ def printable_target_name
78
+ resolve_value(_printable_notification_target_name)
68
79
  end
69
80
 
70
81
  # Returns count of unopened notifications of the target.
71
82
  #
83
+ # @param [Hash] options Options for notification index
84
+ # @option options [Integer] :limit (nil) Limit to query for notifications
72
85
  # @return [Integer] Count of unopened notifications of the target
73
- def unopened_notification_count
74
- unopened_notification_index.count
86
+ # @todo Add filter and reverse options
87
+ def unopened_notification_count(options = {})
88
+ unopened_notification_index(options).count
75
89
  end
76
90
 
77
91
  # Returns if the target has unopened notifications.
78
92
  #
93
+ # @param [Hash] options Options for notification index
94
+ # @option options [Integer] :limit (nil) Limit to query for notifications
79
95
  # @return [Boolean] If the target has unopened notifications
80
- def has_unopened_notifications?
81
- unopened_notification_index.exists?
96
+ # @todo Add filter and reverse options
97
+ def has_unopened_notifications?(options = {})
98
+ unopened_notification_index(options).present?
82
99
  end
83
100
 
84
101
  # Gets automatically arranged notification index of the target.
85
- # When the target has unopened notifications, returns unopened index with unopened_notification_index.
86
- # Otherwise, returns opened index with opened_notification_index.
102
+ # This method is the typical way to get notifications index from controller of view.
103
+ # When the target have unopened notifications, it returns unopened notifications first.
104
+ # Additionaly, it returns opened notifications unless unopened index size overs the limit.
87
105
  # @todo Is this switching the best solution?
88
106
  #
89
107
  # @example Get automatically arranged notification index of the @user
90
108
  # @notifications = @user.notification_index
91
109
  #
92
- # @param [Integer] limit Limit to query for notifications
110
+ # @param [Hash] options Options for notification index
111
+ # @option options [Integer] :limit (nil) Limit to query for notifications
93
112
  # @return [Array<Notificaion>] Notification index of the target
94
- def notification_index(limit = nil)
95
- # When the target have unopened notifications
96
- notifications.unopened_index.exists? ?
97
- # Return unopened notifications
98
- unopened_notification_index(limit) :
99
- # Otherwise, return opened notifications
100
- limit.present? ?
101
- opened_notification_index(limit) :
102
- opened_notification_index
113
+ # @todo Add filter and reverse options
114
+ def notification_index(options = {})
115
+ arrange_notification_index(method(:unopened_notification_index),
116
+ method(:opened_notification_index),
117
+ options)
103
118
  end
104
119
 
105
120
  # Gets unopened notification index of the target.
@@ -107,11 +122,13 @@ module ActivityNotification
107
122
  # @example Get unopened notification index of the @user
108
123
  # @notifications = @user.unopened_notification_index
109
124
  #
110
- # @param [Integer] limit Limit to query for notifications
125
+ # @param [Hash] options Options for notification index
126
+ # @option options [Integer] :limit (nil) Limit to query for notifications
111
127
  # @return [Array<Notificaion>] Unopened notification index of the target
112
- def unopened_notification_index(limit = nil)
113
- limit.present? ?
114
- notifications.unopened_index.limit(limit) :
128
+ # @todo Add filter and reverse options
129
+ def unopened_notification_index(options = {})
130
+ options[:limit].present? ?
131
+ notifications.unopened_index.limit(options[:limit]) :
115
132
  notifications.unopened_index
116
133
  end
117
134
 
@@ -120,9 +137,12 @@ module ActivityNotification
120
137
  # @example Get opened notification index of the @user
121
138
  # @notifications = @user.opened_notification_index(10)
122
139
  #
123
- # @param [Integer] limit Limit to query for notifications
140
+ # @param [Hash] options Options for notification index
141
+ # @option options [Integer] :limit (ActivityNotification.config.opened_index_limit) Limit to query for notifications
124
142
  # @return [Array<Notificaion>] Opened notification index of the target
125
- def opened_notification_index(limit = ActivityNotification.config.opened_limit)
143
+ # @todo Add filter and reverse options
144
+ def opened_notification_index(options = {})
145
+ limit = options[:limit] || ActivityNotification.config.opened_index_limit
126
146
  notifications.opened_index(limit)
127
147
  end
128
148
 
@@ -149,8 +169,12 @@ module ActivityNotification
149
169
  #
150
170
  # @param [Hash] options Options for opening notifications
151
171
  # @option options [DateTime] :opened_at (DateTime.now) Time to set to opened_at of the notification record
172
+ # @option options [String] :filtered_by_type (nil) Notifiable type for filter
173
+ # @option options [Object] :filtered_by_group (nil) Group instance for filter
174
+ # @option options [String] :filtered_by_group_type (nil) Group type for filter, valid with :filtered_by_group_id
175
+ # @option options [String] :filtered_by_group_id (nil) Group instance id for filter, valid with :filtered_by_group_type
176
+ # @option options [String] :filtered_by_key (nil) Key of the notification for filter
152
177
  # @return [Integer] Number of opened notification records
153
- # @todo Add filter option
154
178
  def open_all_notifications(options = {})
155
179
  Notification.open_all_of(self, options)
156
180
  end
@@ -158,21 +182,21 @@ module ActivityNotification
158
182
 
159
183
  # Gets automatically arranged notification index of the target with included attributes like target, notifiable, group and notifier.
160
184
  # This method is the typical way to get notifications index from controller of view.
185
+ # When the target have unopened notifications, it returns unopened notifications first.
186
+ # Additionaly, it returns opened notifications unless unopened index size overs the limit.
187
+ # @todo Is this switching the best solution?
161
188
  #
162
189
  # @example Get automatically arranged notification index of the @user with included attributes
163
190
  # @notifications = @user.notification_index_with_attributes
164
191
  #
165
- # @param [Integer] limit Limit to query for notifications
192
+ # @param [Hash] options Options for notification index
193
+ # @option options [Integer] :limit (nil) Limit to query for notifications
166
194
  # @return [Array<Notificaion>] Notification index of the target with attributes
167
- def notification_index_with_attributes(limit = nil)
168
- # When the target have unopened notifications
169
- unopened_notification_index.exists? ?
170
- # Return unopened notifications
171
- unopened_notification_index_with_attributes(limit) :
172
- # Otherwise, return opened notifications
173
- limit.present? ?
174
- opened_notification_index_with_attributes(limit) :
175
- opened_notification_index_with_attributes
195
+ # @todo Add filter and reverse options
196
+ def notification_index_with_attributes(options = {})
197
+ arrange_notification_index(method(:unopened_notification_index_with_attributes),
198
+ method(:opened_notification_index_with_attributes),
199
+ options)
176
200
  end
177
201
 
178
202
  # Gets unopened notification index of the target with included attributes like target, notifiable, group and notifier.
@@ -180,10 +204,12 @@ module ActivityNotification
180
204
  # @example Get unopened notification index of the @user with included attributes
181
205
  # @notifications = @user.unopened_notification_index_with_attributes
182
206
  #
183
- # @param [Integer] limit Limit to query for notifications
207
+ # @param [Hash] options Options for notification index
208
+ # @option options [Integer] :limit (nil) Limit to query for notifications
184
209
  # @return [Array<Notificaion>] Unopened notification index of the target with attributes
185
- def unopened_notification_index_with_attributes(limit = nil)
186
- include_attributes unopened_notification_index(limit)
210
+ # @todo Add filter and reverse options
211
+ def unopened_notification_index_with_attributes(options = {})
212
+ include_attributes unopened_notification_index(options)
187
213
  end
188
214
 
189
215
  # Gets opened notification index of the target with including attributes like target, notifiable, group and notifier.
@@ -191,10 +217,12 @@ module ActivityNotification
191
217
  # @example Get opened notification index of the @user with included attributes
192
218
  # @notifications = @user.opened_notification_index_with_attributes(10)
193
219
  #
194
- # @param [Integer] limit Limit to query for notifications
220
+ # @param [Hash] options Options for notification index
221
+ # @option options [Integer] :limit (ActivityNotification.config.opened_index_limit) Limit to query for notifications
195
222
  # @return [Array<Notificaion>] Opened notification index of the target with attributes
196
- def opened_notification_index_with_attributes(limit = ActivityNotification.config.opened_limit)
197
- include_attributes opened_notification_index(limit)
223
+ # @todo Add filter and reverse options
224
+ def opened_notification_index_with_attributes(options = {})
225
+ include_attributes opened_notification_index(options)
198
226
  end
199
227
 
200
228
  private
@@ -204,15 +232,46 @@ module ActivityNotification
204
232
  # Otherwise, target, notifiable and or notifier will be include without group.
205
233
  # @api private
206
234
  #
207
- # @param [Array<Notificaion>] notification_index Notification index
208
- # @return [Array<Notificaion>] Notification index with attributes
209
- def include_attributes(notification_index)
210
- if notification_index.present?
211
- Notification.group_member_exists?(notification_index) ?
212
- notification_index.with_target.with_notifiable.with_group.with_notifier :
213
- notification_index.with_target.with_notifiable.with_notifier
235
+ # @param [ActiveRecord_AssociationRelation<Notificaion>] target_index Notification index
236
+ # @return [ActiveRecord_AssociationRelation<Notificaion>] Notification index with attributes
237
+ def include_attributes(target_index)
238
+ if target_index.present?
239
+ Notification.group_member_exists?(target_index) ?
240
+ target_index.with_target.with_notifiable.with_group.with_notifier :
241
+ target_index.with_target.with_notifiable.with_notifier
242
+ else
243
+ Notification.none
244
+ end
245
+ end
246
+
247
+ # Gets automatically arranged notification index of the target.
248
+ # When the target have unopened notifications, it returns unopened notifications first.
249
+ # Additionaly, it returns opened notifications unless unopened index size overs the limit.
250
+ # @api private
251
+ # @todo Is this switching the best solution?
252
+ #
253
+ # @param [Method] loading_unopened_index_method Method to load unopened index
254
+ # @param [Method] loading_opened_index_method Method to load opened index
255
+ # @param [Hash] options Options for notification index
256
+ # @option options [Integer] :limit (nil) Limit to query for notifications
257
+ # @return [Array<Notificaion>] Notification index of the target
258
+ def arrange_notification_index(loading_unopened_index_method, loading_opened_index_method, options = {})
259
+ # When the target have unopened notifications
260
+ if has_unopened_notifications?(options)
261
+ # Return unopened notifications first
262
+ target_unopened_index = loading_unopened_index_method.call(options).to_a
263
+ # Total limit if notification index
264
+ total_limit = options[:limit] || ActivityNotification.config.opened_index_limit
265
+ # Additionaly, return opened notifications unless unopened index size overs the limit
266
+ if (opened_limit = total_limit - target_unopened_index.size) > 0
267
+ target_opened_index = loading_opened_index_method.call(options.merge(limit: opened_limit))
268
+ target_unopened_index.concat(target_opened_index.to_a)
269
+ else
270
+ target_unopened_index
271
+ end
214
272
  else
215
- notifications.none
273
+ # Otherwise, return opened notifications
274
+ loading_opened_index_method.call(options)
216
275
  end
217
276
  end
218
277