activity_notification 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
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