activity_notification 0.0.9 → 0.0.10

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.travis.yml +5 -0
  4. data/.yardopts +3 -0
  5. data/Gemfile +5 -0
  6. data/Gemfile.lock +50 -44
  7. data/README.md +242 -81
  8. data/Rakefile +13 -13
  9. data/activity_notification.gemspec +6 -8
  10. data/app/controllers/activity_notification/notifications_controller.rb +89 -11
  11. data/app/controllers/activity_notification/notifications_with_devise_controller.rb +12 -3
  12. data/app/mailers/activity_notification/mailer.rb +3 -0
  13. data/gemfiles/Gemfile.rails-4.2 +13 -0
  14. data/gemfiles/Gemfile.rails-4.2.lock +190 -0
  15. data/gemfiles/Gemfile.rails-5.0 +14 -0
  16. data/gemfiles/Gemfile.rails-5.0.lock +201 -0
  17. data/lib/activity_notification.rb +10 -6
  18. data/lib/activity_notification/apis/notification_api.rb +137 -27
  19. data/lib/activity_notification/common.rb +48 -24
  20. data/lib/activity_notification/config.rb +68 -10
  21. data/lib/activity_notification/controllers/store_controller.rb +13 -5
  22. data/lib/activity_notification/helpers/polymorphic_helpers.rb +17 -3
  23. data/lib/activity_notification/helpers/view_helpers.rb +161 -45
  24. data/lib/activity_notification/mailers/helpers.rb +121 -83
  25. data/lib/activity_notification/models/concerns/notifiable.rb +162 -69
  26. data/lib/activity_notification/models/concerns/notifier.rb +2 -0
  27. data/lib/activity_notification/models/concerns/target.rb +124 -25
  28. data/lib/activity_notification/models/notification.rb +168 -4
  29. data/lib/activity_notification/rails/routes.rb +50 -48
  30. data/lib/activity_notification/renderable.rb +106 -26
  31. data/lib/activity_notification/roles/acts_as_notifiable.rb +99 -26
  32. data/lib/activity_notification/roles/acts_as_notifier.rb +3 -0
  33. data/lib/activity_notification/roles/acts_as_target.rb +70 -0
  34. data/lib/activity_notification/version.rb +1 -1
  35. data/lib/generators/activity_notification/active_record/migration_generator.rb +3 -1
  36. data/lib/generators/activity_notification/controllers_generator.rb +5 -0
  37. data/lib/generators/activity_notification/install_generator.rb +7 -3
  38. data/lib/generators/activity_notification/models/notification_generator.rb +4 -2
  39. data/lib/generators/activity_notification/views_generator.rb +20 -0
  40. data/spec/concerns/apis/notification_api_spec.rb +105 -36
  41. data/spec/concerns/common_spec.rb +1 -1
  42. data/spec/concerns/models/notifiable_spec.rb +2 -2
  43. data/spec/concerns/models/notifier_spec.rb +1 -1
  44. data/spec/concerns/models/target_spec.rb +9 -8
  45. data/spec/controllers/notifications_controller_shared_examples.rb +101 -28
  46. data/spec/controllers/notifications_with_devise_controller_spec.rb +14 -4
  47. data/spec/helpers/view_helpers_spec.rb +3 -3
  48. data/spec/mailers/mailer_spec.rb +1 -1
  49. data/spec/models/notification_spec.rb +57 -3
  50. data/spec/rails_app/app/models/article.rb +1 -2
  51. data/spec/rails_app/app/models/comment.rb +8 -6
  52. data/spec/rails_app/app/models/user.rb +1 -1
  53. data/spec/rails_app/app/views/layouts/_header.html.erb +2 -0
  54. data/spec/rails_app/config/application.rb +3 -1
  55. data/spec/rails_app/config/environment.rb +12 -2
  56. data/spec/rails_app/config/environments/test.rb +11 -2
  57. data/spec/roles/acts_as_notifiable_spec.rb +2 -2
  58. data/spec/roles/acts_as_notifier_spec.rb +1 -1
  59. data/spec/roles/acts_as_target_spec.rb +3 -3
  60. data/spec/spec_helper.rb +6 -0
  61. metadata +35 -40
  62. data/spec/rails_app/app/models/concerns/.keep +0 -0
@@ -2,61 +2,61 @@ require "active_support/core_ext/object/try"
2
2
  require "active_support/core_ext/hash/slice"
3
3
 
4
4
  module ActionDispatch::Routing
5
+ # Extended ActionDispatch::Routing::Mapper implementation to add routing method of ActivityNotification.
5
6
  class Mapper
6
- # Includes notify_to method for routes.
7
- # This method is responsible to generate all needed routes for activity_notification
8
- #
9
- # ==== Examples
10
- #
11
- # notify_to :users
12
- # notify_to :users, with_devise: :users
13
- # notify_to :users, with_devise: :users, only: [:open, :open_all, :move]
7
+ # Includes notify_to method for routes, which is responsible to generate all necessary routes for activity_notification.
14
8
  #
15
9
  # When you have an User model configured as a target (e.g. defined acts_as_target),
16
- # you can creat this inside your routes:
17
- #
10
+ # you can create as follows in your routes:
18
11
  # notify_to :users
19
- #
20
12
  # This method creates the needed routes:
13
+ # # Notification routes
14
+ # user_notifications GET /users/:user_id/notifications(.:format)
15
+ # { controller:"activity_notification/notifications", action:"index", target_type:"users" }
16
+ # user_notification GET /users/:user_id/notifications/:id(.:format)
17
+ # { controller:"activity_notification/notifications", action:"show", target_type:"users" }
18
+ # user_notification DELETE /users/:user_id/notifications/:id(.:format)
19
+ # { controller:"activity_notification/notifications", action:"destroy", target_type:"users" }
20
+ # open_all_user_notifications POST /users/:user_id/notifications/open_all(.:format)
21
+ # { controller:"activity_notification/notifications", action:"open_all", target_type:"users" }
22
+ # move_user_notification POST /users/:user_id/notifications/:id/move(.:format)
23
+ # { controller:"activity_notification/notifications", action:"move", target_type:"users" }
24
+ # open_user_notification POST /users/:user_id/notifications/:id/open(.:format)
25
+ # { controller:"activity_notification/notifications", action:"open", target_type:"users" }
21
26
  #
22
- # # Notification routes
23
- # user_notifications GET /users/:user_id/notifications(.:format)
24
- # {controller:"activity_notification/notifications", action:"index", target_type:"users"}
25
- # user_notification GET /users/:user_id/notifications/:id(.:format)
26
- # {controller:"activity_notification/notifications", action:"show", target_type:"users"}
27
- # user_notification DELETE /users/:user_id/notifications/:id(.:format)
28
- # {controller:"activity_notification/notifications", action:"destroy", target_type:"users"}
29
- # open_all_user_notifications POST /users/:user_id/notifications/open_all(.:format)
30
- # {controller:"activity_notification/notifications", action:"open_all", target_type:"users"}
31
- # move_user_notification POST /users/:user_id/notifications/:id/move(.:format)
32
- # {controller:"activity_notification/notifications", action:"move", target_type:"users"}
33
- # open_user_notification POST /users/:user_id/notifications/:id/open(.:format)
34
- # {controller:"activity_notification/notifications", action:"open", target_type:"users"}
35
- #
36
- # When you use devise for authentication and you want make notification target assciated with devise,
37
- # you can creat this inside your routes:
38
- #
39
- # notify_to :users, with_devise: true
40
- #
27
+ # When you use devise authentication and you want make notification targets assciated with devise,
28
+ # you can create as follows in your routes:
29
+ # notify_to :users, with_devise: :users
41
30
  # This with_devise option creates the needed routes assciated with devise authentication:
31
+ # # Notification with devise routes
32
+ # user_notifications GET /users/:user_id/notifications(.:format)
33
+ # { controller:"activity_notification/notifications_with_devise", action:"index", target_type:"users", devise_type:"users" }
34
+ # user_notification GET /users/:user_id/notifications/:id(.:format)
35
+ # { controller:"activity_notification/notifications_with_devise", action:"show", target_type:"users", devise_type:"users" }
36
+ # user_notification DELETE /users/:user_id/notifications/:id(.:format)
37
+ # { controller:"activity_notification/notifications_with_devise", action:"destroy", target_type:"users", devise_type:"users" }
38
+ # open_all_user_notifications POST /users/:user_id/notifications/open_all(.:format)
39
+ # { controller:"activity_notification/notifications_with_devise", action:"open_all", target_type:"users", devise_type:"users" }
40
+ # move_user_notification POST /users/:user_id/notifications/:id/move(.:format)
41
+ # { controller:"activity_notification/notifications_with_devise", action:"move", target_type:"users", devise_type:"users" }
42
+ # open_user_notification POST /users/:user_id/notifications/:id/open(.:format)
43
+ # { controller:"activity_notification/notifications_with_devise", action:"open", target_type:"users", devise_type:"users" }
42
44
  #
43
- # # Notification with devise routes
44
- # user_notifications GET /users/:user_id/notifications(.:format)
45
- # {controller:"activity_notification/notifications_with_devise", action:"index", devise_type:"users", target_type:"users"}
46
- # user_notification GET /users/:user_id/notifications/:id(.:format)
47
- # {controller:"activity_notification/notifications_with_devise", action:"show", devise_type:"users", target_type:"users"}
48
- # user_notification DELETE /users/:user_id/notifications/:id(.:format)
49
- # {controller:"activity_notification/notifications_with_devise", action:"destroy", devise_type:"users", target_type:"users"}
50
- # open_all_user_notifications POST /users/:user_id/notifications/open_all(.:format)
51
- # {controller:"activity_notification/notifications_with_devise", action:"open_all", devise_type:"users", target_type:"users"}
52
- # move_user_notification POST /users/:user_id/notifications/:id/move(.:format)
53
- # {controller:"activity_notification/notifications_with_devise", action:"move", devise_type:"users", target_type:"users"}
54
- # open_user_notification POST /users/:user_id/notifications/:id/open(.:format)
55
- # {controller:"activity_notification/notifications_with_devise", action:"open", devise_type:"users", target_type:"users"}
56
- #
57
- # ==== Options
58
- #TODO add document for options
45
+ # @example Define notify_to in config/routes.rb
46
+ # notify_to :users
47
+ # @example Define notify_to with options
48
+ # notify_to :users, only: [:open, :open_all, :move]
49
+ # @example Integrated with Devise authentication
50
+ # notify_to :users, with_devise: :users
59
51
  #
52
+ # @overload notify_to(*resources, *options)
53
+ # @param [Symbol] resources Resources to notify
54
+ # @option options [Symbol] :with_devise Devise resources name for devise integration. Devise integration will be enabled by this option.
55
+ # @option options [String] :controller controller option as resources routing
56
+ # @option options [Symbol] :as as option as resources routing
57
+ # @option options [Array] :only only option as resources routing
58
+ # @option options [Array] :except except option as resources routing
59
+ # @return [ActionDispatch::Routing::Mapper] Routing mapper instance
60
60
  def notify_to(*resources)
61
61
  options = resources.extract_options!
62
62
 
@@ -65,13 +65,14 @@ module ActionDispatch::Routing
65
65
  if (with_devise = options.delete(:with_devise)).present?
66
66
  options[:controller] ||= "activity_notification/notifications_with_devise"
67
67
  options[:as] ||= "notifications"
68
- #TODO check device configuration in model
68
+ #TODO check devise configuration in model
69
69
  devise_defaults = { devise_type: with_devise.to_s }
70
70
  else
71
71
  options[:controller] ||= "activity_notification/notifications"
72
72
  end
73
73
  options[:except] ||= []
74
74
  options[:except].concat( [:new, :create, :edit, :update] )
75
+ notification_resources = options[:model] || :notifications
75
76
 
76
77
  #TODO other options
77
78
  # :as, :path_prefix, :path_names ...
@@ -79,7 +80,7 @@ module ActionDispatch::Routing
79
80
  resources.each do |resource|
80
81
  self.resources resource, only: :none do
81
82
  options[:defaults] = (devise_defaults || {}).merge({ target_type: resource.to_s })
82
- self.resources :notifications, options do
83
+ self.resources notification_resources, options do
83
84
  collection do
84
85
  post :open_all unless ignore_path?(:open_all, options)
85
86
  end
@@ -91,6 +92,7 @@ module ActionDispatch::Routing
91
92
  end
92
93
  end
93
94
 
95
+ self
94
96
  end
95
97
 
96
98
  private
@@ -1,10 +1,15 @@
1
1
  module ActivityNotification
2
2
  # Provides logic for rendering notifications.
3
- # Handles both i18n strings support and smart partials rendering (different templates per notification key).
4
- # Deeply uses PublicActivity as reference
3
+ # Handles both i18n strings support and smart partials rendering (different templates per the notification key).
4
+ # This module deeply uses PublicActivity gem as reference.
5
5
  module Renderable
6
6
  # Virtual attribute returning text description of the notification
7
7
  # using the notification's key to translate using i18n.
8
+ #
9
+ # @param [Hash] params Parameters for rendering notification text
10
+ # @option params [String] :target Target type name to use as i18n text key
11
+ # @option params [Hash] others Parameters to be reffered in i18n text
12
+ # @return [String] Rendered text
8
13
  def text(params = {})
9
14
  k = key.split('.')
10
15
  k.unshift('notification') if k.first != 'notification'
@@ -21,20 +26,17 @@ module ActivityNotification
21
26
 
22
27
  # Renders notification from views.
23
28
  #
24
- # @param [ActionView::Base] context
25
- # @return [nil] nil
26
- #
27
29
  # The preferred way of rendering notifications is
28
30
  # to provide a template specifying how the rendering should be happening.
29
- # However, you can choose using _I18n_ based approach when developing
31
+ # However, you can choose using _i18n_ based approach when developing
30
32
  # an application that supports plenty of languages.
31
33
  #
32
- # If partial view exists that matches the "key" attribute
34
+ # If partial view exists that matches the "target" type and "key" attribute
33
35
  # renders that partial with local variables set to contain both
34
- # Activity and activity_parameters (hash with indifferent access).
36
+ # Notification and notification_parameters (hash with indifferent access).
35
37
  #
36
38
  # If the partial view does not exist and you wish to fallback to rendering
37
- # through the I18n translation, you can do so by passing in a :fallback
39
+ # through the i18n translation, you can do so by passing in a :fallback
38
40
  # parameter whose value equals :text.
39
41
  #
40
42
  # If you do not want to define a partial view, and instead want to have
@@ -42,48 +44,99 @@ module ActivityNotification
42
44
  # value equal to the partial you wish to use when the partial defined
43
45
  # by the notification key does not exist.
44
46
  #
45
- # @example Render a list of all @target's notifications of from a view (erb)
47
+ # Render a list of all notifications of @target from a view (erb):
46
48
  # <ul>
47
49
  # <% @target.notifications.each do |notification| %>
48
- # <li><%= render_notification(notification) %></li>
50
+ # <li><%= render_notification notification %></li>
49
51
  # <% end %>
50
52
  # </ul>
51
53
  #
52
- # @example Fallback to the I18n text translation if the view is missing
54
+ # Fallback to the i18n text translation if the view is missing:
53
55
  # <ul>
54
56
  # <% @target.notifications.each do |notification| %>
55
- # <li><%= render_notification(notification, fallback: :text) %></li>
57
+ # <li><%= render_notification notification, fallback: :text %></li>
56
58
  # <% end %>
57
59
  # </ul>
58
60
  #
59
- # @example Fallback to a default view if the view for the current notification key is missing.
60
- # The string is the partial name you wish to use.
61
+ # Fallback to a default view if the view for the current notification key is missing:
61
62
  # <ul>
62
63
  # <% @target.notifications.each do |notification| %>
63
- # <li><%= render_notification(notification, fallback: 'default') %></li>
64
+ # <li><%= render_notification notification, fallback: 'default' %></li>
64
65
  # <% end %>
65
66
  # </ul>
66
67
  #
67
- # # Layouts
68
- #TODO
68
+ # = Layouts
69
+ #
70
+ # You can supply a layout that will be used for notification partials
71
+ # with :layout param.
72
+ # Keep in mind that layouts for partials are also partials.
73
+ #
74
+ # Supply a layout:
75
+ # # in views:
76
+ # # All examples look for a layout in app/views/layouts/_notification.erb
77
+ # render_notification @notification, layout: "notification"
78
+ # render_notification @notification, layout: "layouts/notification"
79
+ # render_notification @notification, layout: :notification
80
+ #
81
+ # # app/views/layouts/_notification.erb
82
+ # <p><%= notification.created_at %></p>
83
+ # <%= yield %>
69
84
  #
70
- # # Creating a template
85
+ # == Custom Layout Location
86
+ #
87
+ # You can customize the layout directory by supplying :layout_root
88
+ # or by using an absolute path.
89
+ #
90
+ # Declare custom layout location:
91
+ # # Both examples look for a layout in "app/views/custom/_layout.erb"
92
+ # render_notification @notification, layout_root: "custom"
93
+ # render_notification @notification, layout: "/custom/layout"
94
+ #
95
+ # = Creating a template
71
96
  #
72
97
  # To use templates for formatting how the notification should render,
73
98
  # create a template based on target type and notification key, for example:
74
99
  #
75
100
  # Given a target type users and key _notification.article.create_, create directory tree
76
- # _app/views/activity_notifications/users/article/_ and create the _create_ partial there
101
+ # _app/views/activity_notification/notifications/users/article/_ and create the _create_ partial there
77
102
  #
78
103
  # Note that if a key consists of more than three parts splitted by commas, your
79
104
  # directory structure will have to be deeper, for example:
80
- # notification.article.comments.destroy => app/views/activity_notifications/users/articles/comments/_destroy.html.erb
105
+ # notification.article.comment.reply => app/views/activity_notification/notifications/users/article/comment/_reply.html.erb
106
+ #
107
+ # == Custom Directory
108
+ #
109
+ # You can override the default `activity_notification/notifications/#{target}` template root with the :partial_root parameter.
110
+ #
111
+ # Custom template root:
112
+ # # look for templates inside of /app/views/custom instead of /app/views/public_directory/activity_notification/notifications/#{target}
113
+ # render_notification @notification, partial_root: "custom"
81
114
  #
82
- # ## Custom Directory
83
- #TODO
115
+ # == Variables in templates
84
116
  #
85
- # ## Variables in templates
86
- #TODO
117
+ # From within a template there are three variables at your disposal:
118
+ #
119
+ # * notification
120
+ # * controller
121
+ # * parameters [converted into a HashWithIndifferentAccess]
122
+ #
123
+ # Template for key: _notification.article.create_ (erb):
124
+ # <p>
125
+ # Article <strong><%= parameters[:title] %></strong>
126
+ # was posted by <em><%= parameters["author"] %></em>
127
+ # <%= distance_of_time_in_words_to_now(notification.created_at) %>
128
+ # </p>
129
+ #
130
+ # @param [ActionView::Base] context
131
+ # @param [Hash] params Parameters for rendering notifications
132
+ # @option params [String, Symbol] :target (nil) Target type name to find template or i18n text
133
+ # @option params [String] :partial_root ("activity_notification/notifications/#{target}", controller.target_view_path, 'activity_notification/notifications/default') Partial template name
134
+ # @option params [String] :partial (self.key.gsub('.', '/')) Root path of partial template
135
+ # @option params [String] :layout (nil) Layout template name
136
+ # @option params [String] :layout_root ('layouts') Root path of layout template
137
+ # @option params [String] :fallback (nil) Fallback template to use when MissingTemplate is raised. Set :text to use i18n text as fallback.
138
+ # @option params [Hash] others Parameters to be set as locals
139
+ # @return [String] Rendered view or text as string
87
140
  def render(context, params = {})
88
141
  params[:i18n] and return context.render text: self.text(params)
89
142
 
@@ -105,6 +158,12 @@ module ActivityNotification
105
158
  end
106
159
  end
107
160
 
161
+ # Returns partial path from options
162
+ #
163
+ # @param [String] path Partial template name
164
+ # @param [String] root Root path of partial template
165
+ # @param [String, Symbol] target Target type name to find template
166
+ # @return [String] Partial template path
108
167
  def partial_path(path = nil, root = nil, target = nil)
109
168
  controller = ActivityNotification.get_controller if ActivityNotification.respond_to?(:get_controller)
110
169
  root ||= "activity_notification/notifications/#{target}" if target.present?
@@ -114,27 +173,48 @@ module ActivityNotification
114
173
  select_path(path, root)
115
174
  end
116
175
 
176
+ # Returns layout path from options
177
+ #
178
+ # @param [String] path Layout template name
179
+ # @param [String] root Root path of layout template
180
+ # @return [String] Layout template path
117
181
  def layout_path(path = nil, root = nil)
118
182
  path.nil? and return
119
183
  root ||= 'layouts'
120
184
  select_path(path, root)
121
185
  end
122
186
 
187
+ # Returns locals parameter for view
188
+ # There are three variables to be add by method:
189
+ # * notification
190
+ # * controller
191
+ # * parameters [converted into a HashWithIndifferentAccess]
192
+ #
193
+ # @param [Hash] params Parameters to add parameters at locals
194
+ # @return [Hash] locals parameter
123
195
  def prepare_locals(params)
124
196
  locals = params.delete(:locals) || {}
125
-
126
197
  prepared_parameters = prepare_parameters(params)
127
198
  locals.merge\
128
199
  notification: self,
200
+ controller: ActivityNotification.get_controller,
129
201
  parameters: prepared_parameters
130
202
  end
131
203
 
204
+ # Prepares parameters with @prepared_params.
205
+ # Converted into a HashWithIndifferentAccess.
206
+ #
207
+ # @param [Hash] params Parameters to prepare
208
+ # @return [Hash] Prepared parameters
132
209
  def prepare_parameters(params)
133
210
  @prepared_params ||= self.parameters.with_indifferent_access.merge(params)
134
211
  end
135
212
 
213
+
136
214
  private
137
215
 
216
+ # Select template path
217
+ # @api private
138
218
  def select_path(path, root)
139
219
  [root, path].map(&:to_s).join('/')
140
220
  end
@@ -1,52 +1,125 @@
1
1
  module ActivityNotification
2
+ # Manages to add all required configurations to notifiable models.
2
3
  module ActsAsNotifiable
3
4
  extend ActiveSupport::Concern
4
5
 
5
6
  class_methods do
6
- # Adds required callbacks for creating and updating notifiable models.
7
+ # Adds required configurations to notifiable models.
7
8
  #
8
9
  # == Parameters:
9
- # [:targets, :group, :notifier, :parameters, :email_allowed, :notifiable_path]
10
- # targets: Targets to send notification. It it set as ActiveRecord records or array of models.
11
- # This is a only necessary option. If you do not specify this option, you have to override
12
- # notification_targets or notification_[plural target type] (e.g. notification_users) method.
10
+ # * :targets
11
+ # * Targets to send notifications.
12
+ # It it set as ActiveRecord records or array of models.
13
+ # This is a only necessary option.
14
+ # If you do not specify this option, you have to override notification_targets
15
+ # or notification_[plural target type] (e.g. notification_users) method.
16
+ # @example Notify to all users
17
+ # class Comment < ActiveRecord::Base
18
+ # acts_as_notifiable :users, targets: User.all
19
+ # end
20
+ # @example Notify to author and users commented to the article, except comment owner self
21
+ # class Comment < ActiveRecord::Base
22
+ # belongs_to :article
23
+ # belongs_to :user
24
+ # acts_as_notifiable :users,
25
+ # targets: ->(comment, key) {
26
+ # ([comment.article.user] + comment.article.commented_users.to_a - [comment.user]).uniq
27
+ # }
28
+ # end
13
29
  #
14
- # group: Group unit of notifications. Notifications will be bundled by this group (and target, notifiable_type, key).
15
- # This parameter is a optional.
30
+ # * :group
31
+ # * Group unit of notifications.
32
+ # Notifications will be bundled by this group (and target, notifiable_type, key).
33
+ # This parameter is a optional.
34
+ # @example All *unopened* notifications to the same target will be grouped by `article`
35
+ # class Comment < ActiveRecord::Base
36
+ # belongs_to :article
37
+ # acts_as_notifiable :users, targets: User.all, group: :article
38
+ # end
16
39
  #
17
- # notifier: Notifier of the notification.This will be stored as notifier with notification record.
18
- # This parameter is a optional.
40
+ # * :notifier
41
+ # * Notifier of the notification.
42
+ # This will be stored as notifier with notification record.
43
+ # This parameter is a optional.
44
+ # @example Set comment owner self as notifier
45
+ # class Comment < ActiveRecord::Base
46
+ # belongs_to :article
47
+ # belongs_to :user
48
+ # acts_as_notifiable :users, targets: User.all, notifier: :user
49
+ # end
19
50
  #
20
- # parameters: Parameter to add notification data. This will be stored as parameters with notification record.
21
- # This parameter is a optional.
51
+ # * :parameters
52
+ # * Additional parameters of the notifications.
53
+ # This will be stored as parameters with notification record.
54
+ # You can use these additional parameters in your notification view or i18n text.
55
+ # This parameter is a optional.
56
+ # @example Set constant values as additional parameter
57
+ # class Comment < ActiveRecord::Base
58
+ # acts_as_notifiable :users, targets: User.all, parameters: { default_param: '1' }
59
+ # end
60
+ # @example Set comment body as additional parameter
61
+ # class Comment < ActiveRecord::Base
62
+ # acts_as_notifiable :users, targets: User.all, parameters: ->(comment, key) { body: comment.body }
63
+ # end
22
64
  #
23
- # email_allowed: If activity_notification sends notification email to these targets.
24
- # Specified method or symbol is expected to return true (not nil) or false (nil).
25
- # This parameter is a optional since default value is false.
26
- # To use notification email, email_allowed option must return true (not nil) in both of notifiable and target model.
27
- # This can be also configured default option in initializer.
65
+ # * :email_allowed
66
+ # * Whether activity_notification sends notification email.
67
+ # Specified method or symbol is expected to return true (not nil) or false (nil).
68
+ # This parameter is a optional since default value is false.
69
+ # To use notification email, email_allowed option must return true (not nil) in both of notifiable and target model.
70
+ # This can be also configured default option in initializer.
71
+ # @example Enable email notification for this notifiable model
72
+ # class Comment < ActiveRecord::Base
73
+ # acts_as_notifiable :users, targets: User.all, email_allowed: true
74
+ # end
28
75
  #
29
- # notifiable_path: Path to redirect from open or move action of notification controller.
30
- # You can use this notifiable_path as notifiable link in notification view.
31
- # This parameter is a optional since polymorphic_path is used as default value.
76
+ # * :notifiable_path
77
+ # * Path to redirect from open or move action of notification controller.
78
+ # You can also use this notifiable_path as notifiable link in notification view.
79
+ # This parameter is a optional since polymorphic_path is used as default value.
80
+ # @example Redirect to parent article page from comment notifications
81
+ # class Comment < ActiveRecord::Base
82
+ # belongs_to :article
83
+ # acts_as_notifiable :users, targets: User.all, notifiable_path: :article_notifiable_path
84
+ #
85
+ # def article_notifiable_path
86
+ # article_path(article)
87
+ # end
88
+ # end
89
+ #
90
+ # @param [Symbol] target_type Type of notification target as symbol
91
+ # @param [Hash] options Options for notifiable model configuration
92
+ # @option options [Symbol, Proc, Array] :targets (nil) Targets to send notifications
93
+ # @option options [Symbol, Proc, Object] :group (nil) Group unit of the notifications
94
+ # @option options [Symbol, Proc, Object] :notifier (nil) Notifier of the notifications
95
+ # @option options [Symbol, Proc, Hash] :parameters ({}) Additional parameters of the notifications
96
+ # @option options [Symbol, Proc, Boolean] :email_allowed (ActivityNotification.config.email_enabled) Whether activity_notification sends notification email
97
+ # @option options [Symbol, Proc, String] :notifiable_path (polymorphic_path(self)) Path to redirect from open or move action of notification controller
98
+ # @return [Hash] Configured parameters as notifiable model
32
99
  def acts_as_notifiable(target_type, options = {})
33
100
  include Notifiable
34
101
  (
35
102
  [:targets, :group, :parameters, :email_allowed].map { |key|
36
- options[key] ?
37
- [key, self.send("_notification_#{key}".to_sym).store(target_type.to_sym, options.delete(key))] :
38
- [nil, nil]
103
+ assign_parameter(target_type, key, "_notification_#{key}", options)
39
104
  }.to_h.merge [:notifier, :notifiable_path].map { |key|
40
- options[key] ?
41
- [key, self.send("_#{key}".to_sym).store(target_type.to_sym, options.delete(key))] :
42
- [nil, nil]
105
+ assign_parameter(target_type, key, "_#{key}", options)
43
106
  }.to_h
44
- ).delete_if { |k, v| k.nil? }
107
+ ).delete_if { |k, _| k.nil? }
45
108
  end
46
109
 
110
+ # Returns array of available notifiable options in acts_as_notifiable.
111
+ # @return [Array<Symbol>] Array of available notifiable options
47
112
  def available_notifiable_options
48
113
  [:targets, :group, :notifier, :parameters, :email_allowed, :notifiable_path].freeze
49
114
  end
115
+
116
+ private
117
+
118
+ def assign_parameter(target_type, key, field_name, options)
119
+ options[key] ?
120
+ [key, self.send(field_name.to_sym).store(target_type.to_sym, options.delete(key))] :
121
+ [nil, nil]
122
+ end
50
123
  end
51
124
  end
52
125
  end