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.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +5 -0
- data/.yardopts +3 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +50 -44
- data/README.md +242 -81
- data/Rakefile +13 -13
- data/activity_notification.gemspec +6 -8
- data/app/controllers/activity_notification/notifications_controller.rb +89 -11
- data/app/controllers/activity_notification/notifications_with_devise_controller.rb +12 -3
- data/app/mailers/activity_notification/mailer.rb +3 -0
- data/gemfiles/Gemfile.rails-4.2 +13 -0
- data/gemfiles/Gemfile.rails-4.2.lock +190 -0
- data/gemfiles/Gemfile.rails-5.0 +14 -0
- data/gemfiles/Gemfile.rails-5.0.lock +201 -0
- data/lib/activity_notification.rb +10 -6
- data/lib/activity_notification/apis/notification_api.rb +137 -27
- data/lib/activity_notification/common.rb +48 -24
- data/lib/activity_notification/config.rb +68 -10
- data/lib/activity_notification/controllers/store_controller.rb +13 -5
- data/lib/activity_notification/helpers/polymorphic_helpers.rb +17 -3
- data/lib/activity_notification/helpers/view_helpers.rb +161 -45
- data/lib/activity_notification/mailers/helpers.rb +121 -83
- data/lib/activity_notification/models/concerns/notifiable.rb +162 -69
- data/lib/activity_notification/models/concerns/notifier.rb +2 -0
- data/lib/activity_notification/models/concerns/target.rb +124 -25
- data/lib/activity_notification/models/notification.rb +168 -4
- data/lib/activity_notification/rails/routes.rb +50 -48
- data/lib/activity_notification/renderable.rb +106 -26
- data/lib/activity_notification/roles/acts_as_notifiable.rb +99 -26
- data/lib/activity_notification/roles/acts_as_notifier.rb +3 -0
- data/lib/activity_notification/roles/acts_as_target.rb +70 -0
- data/lib/activity_notification/version.rb +1 -1
- data/lib/generators/activity_notification/active_record/migration_generator.rb +3 -1
- data/lib/generators/activity_notification/controllers_generator.rb +5 -0
- data/lib/generators/activity_notification/install_generator.rb +7 -3
- data/lib/generators/activity_notification/models/notification_generator.rb +4 -2
- data/lib/generators/activity_notification/views_generator.rb +20 -0
- data/spec/concerns/apis/notification_api_spec.rb +105 -36
- data/spec/concerns/common_spec.rb +1 -1
- data/spec/concerns/models/notifiable_spec.rb +2 -2
- data/spec/concerns/models/notifier_spec.rb +1 -1
- data/spec/concerns/models/target_spec.rb +9 -8
- data/spec/controllers/notifications_controller_shared_examples.rb +101 -28
- data/spec/controllers/notifications_with_devise_controller_spec.rb +14 -4
- data/spec/helpers/view_helpers_spec.rb +3 -3
- data/spec/mailers/mailer_spec.rb +1 -1
- data/spec/models/notification_spec.rb +57 -3
- data/spec/rails_app/app/models/article.rb +1 -2
- data/spec/rails_app/app/models/comment.rb +8 -6
- data/spec/rails_app/app/models/user.rb +1 -1
- data/spec/rails_app/app/views/layouts/_header.html.erb +2 -0
- data/spec/rails_app/config/application.rb +3 -1
- data/spec/rails_app/config/environment.rb +12 -2
- data/spec/rails_app/config/environments/test.rb +11 -2
- data/spec/roles/acts_as_notifiable_spec.rb +2 -2
- data/spec/roles/acts_as_notifier_spec.rb +1 -1
- data/spec/roles/acts_as_target_spec.rb +3 -3
- data/spec/spec_helper.rb +6 -0
- metadata +35 -40
- 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
|
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
|
-
#
|
23
|
-
#
|
24
|
-
#
|
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
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
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
|
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
|
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
|
-
#
|
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
|
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
|
-
#
|
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
|
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
|
-
#
|
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
|
50
|
+
# <li><%= render_notification notification %></li>
|
49
51
|
# <% end %>
|
50
52
|
# </ul>
|
51
53
|
#
|
52
|
-
#
|
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
|
57
|
+
# <li><%= render_notification notification, fallback: :text %></li>
|
56
58
|
# <% end %>
|
57
59
|
# </ul>
|
58
60
|
#
|
59
|
-
#
|
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
|
64
|
+
# <li><%= render_notification notification, fallback: 'default' %></li>
|
64
65
|
# <% end %>
|
65
66
|
# </ul>
|
66
67
|
#
|
67
|
-
#
|
68
|
-
#
|
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
|
-
#
|
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/
|
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.
|
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
|
-
#
|
83
|
-
#TODO
|
115
|
+
# == Variables in templates
|
84
116
|
#
|
85
|
-
#
|
86
|
-
#
|
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
|
7
|
+
# Adds required configurations to notifiable models.
|
7
8
|
#
|
8
9
|
# == Parameters:
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
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
|
-
#
|
15
|
-
#
|
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
|
-
#
|
18
|
-
#
|
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
|
-
#
|
21
|
-
#
|
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
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
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
|
30
|
-
#
|
31
|
-
#
|
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
|
-
|
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
|
-
|
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,
|
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
|