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.
- 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
|