activity_notification 1.5.1 → 1.6.0

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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/README.md +51 -3
  4. data/app/controllers/activity_notification/notifications_controller.rb +1 -1
  5. data/app/controllers/activity_notification/subscriptions_controller.rb +2 -1
  6. data/app/views/activity_notification/notifications/default/_default.html.erb +10 -10
  7. data/app/views/activity_notification/notifications/default/_default_without_grouping.html.erb +10 -10
  8. data/app/views/activity_notification/notifications/default/_index.html.erb +3 -3
  9. data/app/views/activity_notification/notifications/default/index.html.erb +7 -7
  10. data/app/views/activity_notification/notifications/default/open.js.erb +2 -2
  11. data/app/views/activity_notification/notifications/default/open_all.js.erb +2 -2
  12. data/app/views/activity_notification/notifications/default/show.html.erb +2 -2
  13. data/app/views/activity_notification/optional_targets/default/base/_default.text.erb +1 -1
  14. data/app/views/activity_notification/optional_targets/default/slack/_default.text.erb +1 -1
  15. data/app/views/activity_notification/subscriptions/default/_notification_keys.html.erb +2 -2
  16. data/app/views/activity_notification/subscriptions/default/_subscription.html.erb +5 -5
  17. data/app/views/activity_notification/subscriptions/default/show.html.erb +1 -1
  18. data/app/views/activity_notification/subscriptions/default/subscribe.js.erb +1 -1
  19. data/app/views/activity_notification/subscriptions/default/subscribe_to_email.js.erb +1 -1
  20. data/app/views/activity_notification/subscriptions/default/subscribe_to_optional_target.js.erb +1 -1
  21. data/app/views/activity_notification/subscriptions/default/unsubscribe.js.erb +1 -1
  22. data/app/views/activity_notification/subscriptions/default/unsubscribe_to_email.js.erb +1 -1
  23. data/app/views/activity_notification/subscriptions/default/unsubscribe_to_optional_target.js.erb +1 -1
  24. data/lib/activity_notification/apis/subscription_api.rb +2 -2
  25. data/lib/activity_notification/controllers/devise_authentication_controller.rb +16 -0
  26. data/lib/activity_notification/helpers/view_helpers.rb +113 -27
  27. data/lib/activity_notification/models/concerns/subscriber.rb +2 -1
  28. data/lib/activity_notification/models/concerns/target.rb +11 -0
  29. data/lib/activity_notification/rails/routes.rb +169 -40
  30. data/lib/activity_notification/roles/acts_as_target.rb +45 -8
  31. data/lib/activity_notification/version.rb +1 -1
  32. data/spec/controllers/notifications_with_devise_controller_spec.rb +15 -0
  33. data/spec/controllers/subscriptions_controller_shared_examples.rb +4 -3
  34. data/spec/controllers/subscriptions_with_devise_controller_spec.rb +15 -0
  35. data/spec/helpers/view_helpers_spec.rb +1 -1
  36. data/spec/rails_app/app/controllers/articles_controller.rb +2 -0
  37. data/spec/rails_app/app/models/admin.rb +2 -0
  38. data/spec/rails_app/app/views/activity_notification/optional_targets/admins/amazon_sns/comment/_default.text.erb +1 -1
  39. data/spec/rails_app/app/views/articles/index.html.erb +36 -32
  40. data/spec/rails_app/app/views/layouts/_header.html.erb +9 -1
  41. data/spec/rails_app/config/routes.rb +5 -0
  42. metadata +2 -2
@@ -188,14 +188,14 @@ module ActivityNotification
188
188
 
189
189
  protected
190
190
 
191
- # Validates subscribing_to_email cannot be true when subscribing isfalse.
191
+ # Validates subscribing_to_email cannot be true when subscribing is false.
192
192
  def subscribing_to_email_cannot_be_true_when_subscribing_is_false
193
193
  if !subscribing && subscribing_to_email?
194
194
  errors.add(:subscribing_to_email, "cannot be true when subscribing is false")
195
195
  end
196
196
  end
197
197
 
198
- # Validates subscribing_to_optional_target cannot be true when subscribing isfalse.
198
+ # Validates subscribing_to_optional_target cannot be true when subscribing is false.
199
199
  def subscribing_to_optional_target_cannot_be_true_when_subscribing_is_false
200
200
  optional_target_names.each do |optional_target_name|
201
201
  if !subscribing && subscribing_to_optional_target?(optional_target_name)
@@ -27,6 +27,22 @@ module ActivityNotification
27
27
  end
28
28
  end
29
29
 
30
+ # Sets @target instance variable from request parameters.
31
+ # This method override super (ActivityNotiication::CommonController#set_target)
32
+ # to set devise authenticated target when the target_id params is not specified.
33
+ # @api protected
34
+ # @return [Object] Target instance (Returns HTTP 400 when request parameters are not enough)
35
+ def set_target
36
+ target_type = params[:target_type]
37
+ if params[:target_id].blank? && params["#{target_type.to_resource_name}_id"].blank?
38
+ target_class = target_type.to_model_class
39
+ current_resource_method_name = "current_#{params[:devise_type].to_resource_name}"
40
+ params[:target_id] = target_class.resolve_current_devise_target(send(current_resource_method_name))
41
+ render(plain: "403 Forbidden: Unauthenticated as default target", status: 403) and return if params[:target_id].blank?
42
+ end
43
+ super
44
+ end
45
+
30
46
  # Authenticate the target of requested notification with authenticated devise resource.
31
47
  # @api protected
32
48
  # @todo Needs to call authenticate method by more secure way
@@ -40,6 +40,8 @@ module ActivityNotification
40
40
  # @option options [String] :notification_layout (nil) Layout template name of the notification index content
41
41
  # @option options [String] :fallback (nil) Fallback template to use when MissingTemplate is raised. Set :text to use i18n text as fallback.
42
42
  # @option options [String] :partial ('index') Partial template name of the partial index
43
+ # @option options [String] :routing_scope (nil) Routing scope for notification and subscription routes
44
+ # @option options [Boolean] :devise_default_routes (false) If links in default views will be handles as devise default routes
43
45
  # @option options [String] :layout (nil) Layout template name of the partial index
44
46
  # @option options [Integer] :limit (nil) Limit to query for notifications
45
47
  # @option options [Boolean] :reverse (false) If notification index will be ordered as earliest first
@@ -51,7 +53,7 @@ module ActivityNotification
51
53
  # @option options [String] :filtered_by_key (nil) Key of the notification for filter
52
54
  # @option options [Array] :custom_filter (nil) Custom notification filter (e.g. ["created_at >= ?", time.hour.ago])
53
55
  # @return [String] Rendered view or text as string
54
- def render_notification_of target, options = {}
56
+ def render_notification_of(target, options = {})
55
57
  return unless target.is_a? ActivityNotification::Target
56
58
 
57
59
  # Prepare content for notifications index
@@ -77,7 +79,10 @@ module ActivityNotification
77
79
  # @todo Needs any other better implementation
78
80
  # @todo Must handle devise namespace
79
81
  def notifications_path_for(target, params = {})
80
- send("#{target.to_resource_name}_notifications_path", target, params)
82
+ options = params.dup
83
+ options.delete(:devise_default_routes) ?
84
+ send("#{routing_scope(options)}notifications_path", options) :
85
+ send("#{routing_scope(options)}#{target.to_resource_name}_notifications_path", target, options)
81
86
  end
82
87
 
83
88
  # Returns notification_path for the notification
@@ -88,7 +93,10 @@ module ActivityNotification
88
93
  # @todo Needs any other better implementation
89
94
  # @todo Must handle devise namespace
90
95
  def notification_path_for(notification, params = {})
91
- send("#{notification.target.to_resource_name}_notification_path", notification.target, notification, params)
96
+ options = params.dup
97
+ options.delete(:devise_default_routes) ?
98
+ send("#{routing_scope(options)}notification_path", notification, options) :
99
+ send("#{routing_scope(options)}#{notification.target.to_resource_name}_notification_path", notification.target, notification, options)
92
100
  end
93
101
 
94
102
  # Returns move_notification_path for the target of specified notification
@@ -99,7 +107,10 @@ module ActivityNotification
99
107
  # @todo Needs any other better implementation
100
108
  # @todo Must handle devise namespace
101
109
  def move_notification_path_for(notification, params = {})
102
- send("move_#{notification.target.to_resource_name}_notification_path", notification.target, notification, params)
110
+ options = params.dup
111
+ options.delete(:devise_default_routes) ?
112
+ send("move_#{routing_scope(options)}notification_path", notification, options) :
113
+ send("move_#{routing_scope(options)}#{notification.target.to_resource_name}_notification_path", notification.target, notification, options)
103
114
  end
104
115
 
105
116
  # Returns open_notification_path for the target of specified notification
@@ -110,7 +121,10 @@ module ActivityNotification
110
121
  # @todo Needs any other better implementation
111
122
  # @todo Must handle devise namespace
112
123
  def open_notification_path_for(notification, params = {})
113
- send("open_#{notification.target.to_resource_name}_notification_path", notification.target, notification, params)
124
+ options = params.dup
125
+ options.delete(:devise_default_routes) ?
126
+ send("open_#{routing_scope(options)}notification_path", notification, options) :
127
+ send("open_#{routing_scope(options)}#{notification.target.to_resource_name}_notification_path", notification.target, notification, options)
114
128
  end
115
129
 
116
130
  # Returns open_all_notifications_path for the target
@@ -121,7 +135,10 @@ module ActivityNotification
121
135
  # @todo Needs any other better implementation
122
136
  # @todo Must handle devise namespace
123
137
  def open_all_notifications_path_for(target, params = {})
124
- send("open_all_#{target.to_resource_name}_notifications_path", target, params)
138
+ options = params.dup
139
+ options.delete(:devise_default_routes) ?
140
+ send("open_all_#{routing_scope(options)}notifications_path", options) :
141
+ send("open_all_#{routing_scope(options)}#{target.to_resource_name}_notifications_path", target, options)
125
142
  end
126
143
 
127
144
  # Returns notifications_url for the target
@@ -132,7 +149,10 @@ module ActivityNotification
132
149
  # @todo Needs any other better implementation
133
150
  # @todo Must handle devise namespace
134
151
  def notifications_url_for(target, params = {})
135
- send("#{target.to_resource_name}_notifications_url", target, params)
152
+ options = params.dup
153
+ options.delete(:devise_default_routes) ?
154
+ send("#{routing_scope(options)}notifications_url", options) :
155
+ send("#{routing_scope(options)}#{target.to_resource_name}_notifications_url", target, options)
136
156
  end
137
157
 
138
158
  # Returns notification_url for the target of specified notification
@@ -143,7 +163,10 @@ module ActivityNotification
143
163
  # @todo Needs any other better implementation
144
164
  # @todo Must handle devise namespace
145
165
  def notification_url_for(notification, params = {})
146
- send("#{notification.target.to_resource_name}_notification_url", notification.target, notification, params)
166
+ options = params.dup
167
+ options.delete(:devise_default_routes) ?
168
+ send("#{routing_scope(options)}notification_url", notification, options) :
169
+ send("#{routing_scope(options)}#{notification.target.to_resource_name}_notification_url", notification.target, notification, options)
147
170
  end
148
171
 
149
172
  # Returns move_notification_url for the target of specified notification
@@ -154,7 +177,10 @@ module ActivityNotification
154
177
  # @todo Needs any other better implementation
155
178
  # @todo Must handle devise namespace
156
179
  def move_notification_url_for(notification, params = {})
157
- send("move_#{notification.target.to_resource_name}_notification_url", notification.target, notification, params)
180
+ options = params.dup
181
+ options.delete(:devise_default_routes) ?
182
+ send("move_#{routing_scope(options)}notification_url", notification, options) :
183
+ send("move_#{routing_scope(options)}#{notification.target.to_resource_name}_notification_url", notification.target, notification, options)
158
184
  end
159
185
 
160
186
  # Returns open_notification_url for the target of specified notification
@@ -165,7 +191,10 @@ module ActivityNotification
165
191
  # @todo Needs any other better implementation
166
192
  # @todo Must handle devise namespace
167
193
  def open_notification_url_for(notification, params = {})
168
- send("open_#{notification.target.to_resource_name}_notification_url", notification.target, notification, params)
194
+ options = params.dup
195
+ options.delete(:devise_default_routes) ?
196
+ send("open_#{routing_scope(options)}notification_url", notification, options) :
197
+ send("open_#{routing_scope(options)}#{notification.target.to_resource_name}_notification_url", notification.target, notification, options)
169
198
  end
170
199
 
171
200
  # Returns open_all_notifications_url for the target of specified notification
@@ -176,7 +205,10 @@ module ActivityNotification
176
205
  # @todo Needs any other better implementation
177
206
  # @todo Must handle devise namespace
178
207
  def open_all_notifications_url_for(target, params = {})
179
- send("open_all_#{target.to_resource_name}_notifications_url", target, params)
208
+ options = params.dup
209
+ options.delete(:devise_default_routes) ?
210
+ send("open_all_#{routing_scope(options)}notifications_url", options) :
211
+ send("open_all_#{routing_scope(options)}#{target.to_resource_name}_notifications_url", target, options)
180
212
  end
181
213
 
182
214
  # Returns subscriptions_path for the target
@@ -186,7 +218,10 @@ module ActivityNotification
186
218
  # @return [String] subscriptions_path for the target
187
219
  # @todo Needs any other better implementation
188
220
  def subscriptions_path_for(target, params = {})
189
- send("#{target.to_resource_name}_subscriptions_path", target, params)
221
+ options = params.dup
222
+ options.delete(:devise_default_routes) ?
223
+ send("#{routing_scope(options)}subscriptions_path", options) :
224
+ send("#{routing_scope(options)}#{target.to_resource_name}_subscriptions_path", target, options)
190
225
  end
191
226
 
192
227
  # Returns subscription_path for the subscription
@@ -196,7 +231,10 @@ module ActivityNotification
196
231
  # @return [String] subscription_path for the subscription
197
232
  # @todo Needs any other better implementation
198
233
  def subscription_path_for(subscription, params = {})
199
- send("#{subscription.target.to_resource_name}_subscription_path", subscription.target, subscription, params)
234
+ options = params.dup
235
+ options.delete(:devise_default_routes) ?
236
+ send("#{routing_scope(options)}subscription_path", subscription, options) :
237
+ send("#{routing_scope(options)}#{subscription.target.to_resource_name}_subscription_path", subscription.target, subscription, options)
200
238
  end
201
239
 
202
240
  # Returns subscribe_subscription_path for the target of specified subscription
@@ -206,7 +244,10 @@ module ActivityNotification
206
244
  # @return [String] subscription_path for the subscription
207
245
  # @todo Needs any other better implementation
208
246
  def subscribe_subscription_path_for(subscription, params = {})
209
- send("subscribe_#{subscription.target.to_resource_name}_subscription_path", subscription.target, subscription, params)
247
+ options = params.dup
248
+ options.delete(:devise_default_routes) ?
249
+ send("subscribe_#{routing_scope(options)}subscription_path", subscription, options) :
250
+ send("subscribe_#{routing_scope(options)}#{subscription.target.to_resource_name}_subscription_path", subscription.target, subscription, options)
210
251
  end
211
252
  alias_method :subscribe_path_for, :subscribe_subscription_path_for
212
253
 
@@ -217,7 +258,10 @@ module ActivityNotification
217
258
  # @return [String] subscription_path for the subscription
218
259
  # @todo Needs any other better implementation
219
260
  def unsubscribe_subscription_path_for(subscription, params = {})
220
- send("unsubscribe_#{subscription.target.to_resource_name}_subscription_path", subscription.target, subscription, params)
261
+ options = params.dup
262
+ options.delete(:devise_default_routes) ?
263
+ send("unsubscribe_#{routing_scope(options)}subscription_path", subscription, options) :
264
+ send("unsubscribe_#{routing_scope(options)}#{subscription.target.to_resource_name}_subscription_path", subscription.target, subscription, options)
221
265
  end
222
266
  alias_method :unsubscribe_path_for, :unsubscribe_subscription_path_for
223
267
 
@@ -228,7 +272,10 @@ module ActivityNotification
228
272
  # @return [String] subscription_path for the subscription
229
273
  # @todo Needs any other better implementation
230
274
  def subscribe_to_email_subscription_path_for(subscription, params = {})
231
- send("subscribe_to_email_#{subscription.target.to_resource_name}_subscription_path", subscription.target, subscription, params)
275
+ options = params.dup
276
+ options.delete(:devise_default_routes) ?
277
+ send("subscribe_to_email_#{routing_scope(options)}subscription_path", subscription, options) :
278
+ send("subscribe_to_email_#{routing_scope(options)}#{subscription.target.to_resource_name}_subscription_path", subscription.target, subscription, options)
232
279
  end
233
280
  alias_method :subscribe_to_email_path_for, :subscribe_to_email_subscription_path_for
234
281
 
@@ -239,7 +286,10 @@ module ActivityNotification
239
286
  # @return [String] subscription_path for the subscription
240
287
  # @todo Needs any other better implementation
241
288
  def unsubscribe_to_email_subscription_path_for(subscription, params = {})
242
- send("unsubscribe_to_email_#{subscription.target.to_resource_name}_subscription_path", subscription.target, subscription, params)
289
+ options = params.dup
290
+ options.delete(:devise_default_routes) ?
291
+ send("unsubscribe_to_email_#{routing_scope(options)}subscription_path", subscription, options) :
292
+ send("unsubscribe_to_email_#{routing_scope(options)}#{subscription.target.to_resource_name}_subscription_path", subscription.target, subscription, options)
243
293
  end
244
294
  alias_method :unsubscribe_to_email_path_for, :unsubscribe_to_email_subscription_path_for
245
295
 
@@ -250,7 +300,10 @@ module ActivityNotification
250
300
  # @return [String] subscription_path for the subscription
251
301
  # @todo Needs any other better implementation
252
302
  def subscribe_to_optional_target_subscription_path_for(subscription, params = {})
253
- send("subscribe_to_optional_target_#{subscription.target.to_resource_name}_subscription_path", subscription.target, subscription, params)
303
+ options = params.dup
304
+ options.delete(:devise_default_routes) ?
305
+ send("subscribe_to_optional_target_#{routing_scope(options)}subscription_path", subscription, options) :
306
+ send("subscribe_to_optional_target_#{routing_scope(options)}#{subscription.target.to_resource_name}_subscription_path", subscription.target, subscription, options)
254
307
  end
255
308
  alias_method :subscribe_to_optional_target_path_for, :subscribe_to_optional_target_subscription_path_for
256
309
 
@@ -261,7 +314,10 @@ module ActivityNotification
261
314
  # @return [String] subscription_path for the subscription
262
315
  # @todo Needs any other better implementation
263
316
  def unsubscribe_to_optional_target_subscription_path_for(subscription, params = {})
264
- send("unsubscribe_to_optional_target_#{subscription.target.to_resource_name}_subscription_path", subscription.target, subscription, params)
317
+ options = params.dup
318
+ options.delete(:devise_default_routes) ?
319
+ send("unsubscribe_to_optional_target_#{routing_scope(options)}subscription_path", subscription, options) :
320
+ send("unsubscribe_to_optional_target_#{routing_scope(options)}#{subscription.target.to_resource_name}_subscription_path", subscription.target, subscription, options)
265
321
  end
266
322
  alias_method :unsubscribe_to_optional_target_path_for, :unsubscribe_to_optional_target_subscription_path_for
267
323
 
@@ -272,7 +328,10 @@ module ActivityNotification
272
328
  # @return [String] subscriptions_url for the target
273
329
  # @todo Needs any other better implementation
274
330
  def subscriptions_url_for(target, params = {})
275
- send("#{target.to_resource_name}_subscriptions_url", target, params)
331
+ options = params.dup
332
+ options.delete(:devise_default_routes) ?
333
+ send("#{routing_scope(options)}subscriptions_url", options) :
334
+ send("#{routing_scope(options)}#{target.to_resource_name}_subscriptions_url", target, options)
276
335
  end
277
336
 
278
337
  # Returns subscription_url for the subscription
@@ -282,7 +341,10 @@ module ActivityNotification
282
341
  # @return [String] subscription_url for the subscription
283
342
  # @todo Needs any other better implementation
284
343
  def subscription_url_for(subscription, params = {})
285
- send("#{subscription.target.to_resource_name}_subscription_url", subscription.target, subscription, params)
344
+ options = params.dup
345
+ options.delete(:devise_default_routes) ?
346
+ send("#{routing_scope(options)}subscription_url", subscription, options) :
347
+ send("#{routing_scope(options)}#{subscription.target.to_resource_name}_subscription_url", subscription.target, subscription, options)
286
348
  end
287
349
 
288
350
  # Returns subscribe_subscription_url for the target of specified subscription
@@ -292,7 +354,10 @@ module ActivityNotification
292
354
  # @return [String] subscription_url for the subscription
293
355
  # @todo Needs any other better implementation
294
356
  def subscribe_subscription_url_for(subscription, params = {})
295
- send("subscribe_#{subscription.target.to_resource_name}_subscription_url", subscription.target, subscription, params)
357
+ options = params.dup
358
+ options.delete(:devise_default_routes) ?
359
+ send("subscribe_#{routing_scope(options)}subscription_url", subscription, options) :
360
+ send("subscribe_#{routing_scope(options)}#{subscription.target.to_resource_name}_subscription_url", subscription.target, subscription, options)
296
361
  end
297
362
  alias_method :subscribe_url_for, :subscribe_subscription_url_for
298
363
 
@@ -303,7 +368,10 @@ module ActivityNotification
303
368
  # @return [String] subscription_url for the subscription
304
369
  # @todo Needs any other better implementation
305
370
  def unsubscribe_subscription_url_for(subscription, params = {})
306
- send("unsubscribe_#{subscription.target.to_resource_name}_subscription_url", subscription.target, subscription, params)
371
+ options = params.dup
372
+ options.delete(:devise_default_routes) ?
373
+ send("unsubscribe_#{routing_scope(options)}subscription_url", subscription, options) :
374
+ send("unsubscribe_#{routing_scope(options)}#{subscription.target.to_resource_name}_subscription_url", subscription.target, subscription, options)
307
375
  end
308
376
  alias_method :unsubscribe_url_for, :unsubscribe_subscription_url_for
309
377
 
@@ -314,7 +382,10 @@ module ActivityNotification
314
382
  # @return [String] subscription_url for the subscription
315
383
  # @todo Needs any other better implementation
316
384
  def subscribe_to_email_subscription_url_for(subscription, params = {})
317
- send("subscribe_to_email_#{subscription.target.to_resource_name}_subscription_url", subscription.target, subscription, params)
385
+ options = params.dup
386
+ options.delete(:devise_default_routes) ?
387
+ send("subscribe_to_email_#{routing_scope(options)}subscription_url", subscription, options) :
388
+ send("subscribe_to_email_#{routing_scope(options)}#{subscription.target.to_resource_name}_subscription_url", subscription.target, subscription, options)
318
389
  end
319
390
  alias_method :subscribe_to_email_url_for, :subscribe_to_email_subscription_url_for
320
391
 
@@ -325,7 +396,10 @@ module ActivityNotification
325
396
  # @return [String] subscription_url for the subscription
326
397
  # @todo Needs any other better implementation
327
398
  def unsubscribe_to_email_subscription_url_for(subscription, params = {})
328
- send("unsubscribe_to_email_#{subscription.target.to_resource_name}_subscription_url", subscription.target, subscription, params)
399
+ options = params.dup
400
+ options.delete(:devise_default_routes) ?
401
+ send("unsubscribe_to_email_#{routing_scope(options)}subscription_url", subscription, options) :
402
+ send("unsubscribe_to_email_#{routing_scope(options)}#{subscription.target.to_resource_name}_subscription_url", subscription.target, subscription, options)
329
403
  end
330
404
  alias_method :unsubscribe_to_email_url_for, :unsubscribe_to_email_subscription_url_for
331
405
 
@@ -336,7 +410,10 @@ module ActivityNotification
336
410
  # @return [String] subscription_url for the subscription
337
411
  # @todo Needs any other better implementation
338
412
  def subscribe_to_optional_target_subscription_url_for(subscription, params = {})
339
- send("subscribe_to_optional_target_#{subscription.target.to_resource_name}_subscription_url", subscription.target, subscription, params)
413
+ options = params.dup
414
+ options.delete(:devise_default_routes) ?
415
+ send("subscribe_to_optional_target_#{routing_scope(options)}subscription_url", subscription, options) :
416
+ send("subscribe_to_optional_target_#{routing_scope(options)}#{subscription.target.to_resource_name}_subscription_url", subscription.target, subscription, options)
340
417
  end
341
418
  alias_method :subscribe_to_optional_target_url_for, :subscribe_to_optional_target_subscription_url_for
342
419
 
@@ -347,7 +424,10 @@ module ActivityNotification
347
424
  # @return [String] subscription_url for the subscription
348
425
  # @todo Needs any other better implementation
349
426
  def unsubscribe_to_optional_target_subscription_url_for(subscription, params = {})
350
- send("unsubscribe_to_optional_target_#{subscription.target.to_resource_name}_subscription_url", subscription.target, subscription, params)
427
+ options = params.dup
428
+ options.delete(:devise_default_routes) ?
429
+ send("unsubscribe_to_optional_target_#{routing_scope(options)}subscription_url", subscription, options) :
430
+ send("unsubscribe_to_optional_target_#{routing_scope(options)}#{subscription.target.to_resource_name}_subscription_url", subscription.target, subscription, options)
351
431
  end
352
432
  alias_method :unsubscribe_to_optional_target_url_for, :unsubscribe_to_optional_target_subscription_url_for
353
433
 
@@ -441,6 +521,12 @@ module ActivityNotification
441
521
  [root, path].map(&:to_s).join('/')
442
522
  end
443
523
 
524
+ # Prepare routing scope from options
525
+ # @api private
526
+ def routing_scope(options = {})
527
+ options[:routing_scope] ? options.delete(:routing_scope).to_s + '_' : ''
528
+ end
529
+
444
530
  end
445
531
 
446
532
  ActionView::Base.class_eval { include ViewHelpers }
@@ -59,7 +59,8 @@ module ActivityNotification
59
59
  subscription.subscribing_to_email? ?
60
60
  subscription.assign_attributes(subscribing_to_email: true, subscribed_to_email_at: created_at) :
61
61
  subscription.assign_attributes(subscribing_to_email: false, unsubscribed_to_email_at: created_at)
62
- optional_targets = subscription.optional_targets
62
+ subscription.optional_targets = (subscription.optional_targets || {}).with_indifferent_access
63
+ optional_targets = {}.with_indifferent_access
63
64
  subscription.optional_target_names.each do |optional_target_name|
64
65
  optional_targets = subscription.subscribing_to_optional_target?(optional_target_name) ?
65
66
  optional_targets.merge(
@@ -20,6 +20,7 @@ module ActivityNotification
20
20
  :_batch_notification_email_allowed,
21
21
  :_notification_subscription_allowed,
22
22
  :_notification_devise_resource,
23
+ :_notification_current_devise_target,
23
24
  :_printable_notification_target_name
24
25
  set_target_class_defaults
25
26
  end
@@ -39,6 +40,7 @@ module ActivityNotification
39
40
  self._batch_notification_email_allowed = ActivityNotification.config.email_enabled
40
41
  self._notification_subscription_allowed = ActivityNotification.config.subscription_enabled
41
42
  self._notification_devise_resource = ->(model) { model }
43
+ self._notification_current_devise_target = ->(current_resource) { current_resource }
42
44
  self._printable_notification_target_name = :printable_name
43
45
  nil
44
46
  end
@@ -130,6 +132,15 @@ module ActivityNotification
130
132
  }.to_h
131
133
  end
132
134
 
135
+ # Resolves current authenticated target by devise authentication from current resource signed in with Devise.
136
+ # This method is able to be overriden.
137
+ #
138
+ # @param [Object] current_resource Current resource signed in with Devise
139
+ # @return [Object] Current authenticated target by devise authentication
140
+ def resolve_current_devise_target(current_resource)
141
+ _notification_current_devise_target.call(current_resource)
142
+ end
143
+
133
144
  # Returns if subscription management is allowed for this target type.
134
145
  # @return [Boolean] If subscription management is allowed for this target type
135
146
  def subscription_enabled?
@@ -26,6 +26,25 @@ module ActionDispatch::Routing
26
26
  # open_user_notification POST /users/:user_id/notifications/:id/open(.:format)
27
27
  # { controller:"activity_notification/notifications", action:"open", target_type:"users" }
28
28
  #
29
+ # You can also configure notification routes with scope like this:
30
+ # scope :myscope, as: :myscope do
31
+ # notify_to :users, routing_scope: :myscope
32
+ # end
33
+ # This routing_scope option creates the needed routes with specified scope like this:
34
+ # # Notification routes
35
+ # myscope_user_notifications GET /myscope/users/:user_id/notifications(.:format)
36
+ # { controller:"activity_notification/notifications", action:"index", target_type:"users", routing_scope: :myscope }
37
+ # myscope_user_notification GET /myscope/users/:user_id/notifications/:id(.:format)
38
+ # { controller:"activity_notification/notifications", action:"show", target_type:"users", routing_scope: :myscope }
39
+ # myscope_user_notification DELETE /myscope/users/:user_id/notifications/:id(.:format)
40
+ # { controller:"activity_notification/notifications", action:"destroy", target_type:"users", routing_scope: :myscope }
41
+ # open_all_myscope_user_notifications POST /myscope/users/:user_id/notifications/open_all(.:format)
42
+ # { controller:"activity_notification/notifications", action:"open_all", target_type:"users", routing_scope: :myscope }
43
+ # move_myscope_user_notification GET /myscope/users/:user_id/notifications/:id/move(.:format)
44
+ # { controller:"activity_notification/notifications", action:"move", target_type:"users", routing_scope: :myscope }
45
+ # open_myscope_user_notification POST /myscope/users/:user_id/notifications/:id/open(.:format)
46
+ # { controller:"activity_notification/notifications", action:"open", target_type:"users", routing_scope: :myscope }
47
+ #
29
48
  # When you use devise authentication and you want make notification targets assciated with devise,
30
49
  # you can create as follows in your routes:
31
50
  # notify_to :users, with_devise: :users
@@ -44,6 +63,23 @@ module ActionDispatch::Routing
44
63
  # open_user_notification POST /users/:user_id/notifications/:id/open(.:format)
45
64
  # { controller:"activity_notification/notifications_with_devise", action:"open", target_type:"users", devise_type:"users" }
46
65
  #
66
+ # When you use with_devise option and you want to make simple default routes as follows, you can use devise_default_routes option:
67
+ # notify_to :users, with_devise: :users, devise_default_routes: true
68
+ # These with_devise and devise_default_routes options create the needed routes assciated with authenticated devise resource as the default target
69
+ # # Notification with default devise routes
70
+ # user_notifications GET /notifications(.:format)
71
+ # { controller:"activity_notification/notifications_with_devise", action:"index", target_type:"users", devise_type:"users" }
72
+ # user_notification GET /notifications/:id(.:format)
73
+ # { controller:"activity_notification/notifications_with_devise", action:"show", target_type:"users", devise_type:"users" }
74
+ # user_notification DELETE /notifications/:id(.:format)
75
+ # { controller:"activity_notification/notifications_with_devise", action:"destroy", target_type:"users", devise_type:"users" }
76
+ # open_all_user_notifications POST /notifications/open_all(.:format)
77
+ # { controller:"activity_notification/notifications_with_devise", action:"open_all", target_type:"users", devise_type:"users" }
78
+ # move_user_notification GET /notifications/:id/move(.:format)
79
+ # { controller:"activity_notification/notifications_with_devise", action:"move", target_type:"users", devise_type:"users" }
80
+ # open_user_notification POST /notifications/:id/open(.:format)
81
+ # { controller:"activity_notification/notifications_with_devise", action:"open", target_type:"users", devise_type:"users" }
82
+ #
47
83
  # When you would like to define subscription management paths with notification paths,
48
84
  # you can create as follows in your routes:
49
85
  # notify_to :users, with_subscription: true
@@ -60,32 +96,36 @@ module ActionDispatch::Routing
60
96
  # notify_to :users, with_devise: :users
61
97
  # @example Define notification paths including subscription paths
62
98
  # notify_to :users, with_subscription: true
99
+ # @example Integrated with Devise authentication as simple default routes including subscription management
100
+ # notify_to :users, with_devise: :users, devise_default_routes: true, with_subscription: true
101
+ # @example Integrated with Devise authentication as simple default routes with scope including subscription management
102
+ # scope :myscope, as: :myscope do
103
+ # notify_to :myscope, with_devise: :users, devise_default_routes: true, with_subscription: true, routing_scope: :myscope
104
+ # end
63
105
  #
64
106
  # @overload notify_to(*resources, *options)
65
107
  # @param [Symbol] resources Resources to notify
66
- # @option options [Symbol] :with_devise (false) Devise resources name for devise integration. Devise integration will be enabled by this option.
67
- # @option options [Hash|Boolean] :with_subscription (false) Subscription path options to define subscription management paths with notification paths. Calls subscribed_by routing when truthy value is passed as this option.
68
- # @option options [String] :model (:notifications) Model name of notifications
69
- # @option options [String] :controller ("activity_notification/notifications" | activity_notification/notifications_with_devise") :controller option as resources routing
70
- # @option options [Symbol] :as (nil) :as option as resources routing
71
- # @option options [Array] :only (nil) :only option as resources routing
72
- # @option options [Array] :except (nil) :except option as resources routing
108
+ # @option options [String] :routing_scope (nil) Routing scope for notification routes
109
+ # @option options [Symbol] :with_devise (false) Devise resources name for devise integration. Devise integration will be enabled by this option.
110
+ # @option options [Boolean] :devise_default_routes (false) Whether you will create routes as device default routes assciated with authenticated devise resource as the default target
111
+ # @option options [Hash|Boolean] :with_subscription (false) Subscription path options to define subscription management paths with notification paths. Calls subscribed_by routing when truthy value is passed as this option.
112
+ # @option options [String] :model (:notifications) Model name of notifications
113
+ # @option options [String] :controller ("activity_notification/notifications" | activity_notification/notifications_with_devise") :controller option as resources routing
114
+ # @option options [Symbol] :as (nil) :as option as resources routing
115
+ # @option options [Array] :only (nil) :only option as resources routing
116
+ # @option options [Array] :except (nil) :except option as resources routing
73
117
  # @return [ActionDispatch::Routing::Mapper] Routing mapper instance
74
118
  def notify_to(*resources)
75
119
  options = create_options(:notifications, resources.extract_options!, [:new, :create, :edit, :update])
76
120
 
77
121
  resources.each do |target|
78
- self.resources target, only: :none do
79
- options[:defaults] = { target_type: target.to_s }.merge(options[:devise_defaults])
80
- resources_options = options.select { |key, _| [:with_devise, :with_subscription, :subscription_option, :model, :devise_defaults].exclude? key }
81
- self.resources options[:model], resources_options do
82
- collection do
83
- post :open_all unless ignore_path?(:open_all, options)
84
- end
85
- member do
86
- get :move unless ignore_path?(:move, options)
87
- post :open unless ignore_path?(:open, options)
88
- end
122
+ options[:defaults] = { target_type: target.to_s }.merge(options[:devise_defaults])
123
+ resources_options = options.select { |key, _| [:with_devise, :devise_default_routes, :with_subscription, :subscription_option, :model, :devise_defaults].exclude? key }
124
+ if options[:with_devise].present? && options[:devise_default_routes].present?
125
+ create_notification_routes options, resources_options
126
+ else
127
+ self.resources target, only: :none do
128
+ create_notification_routes options, resources_options
89
129
  end
90
130
  end
91
131
 
@@ -125,9 +165,36 @@ module ActionDispatch::Routing
125
165
  # unsubscribe_to_optional_target_user_subscription POST /users/:user_id/subscriptions/:id/unsubscribe_to_optional_target(.:format)
126
166
  # { controller:"activity_notification/subscriptions", action:"unsubscribe_to_optional_target", target_type:"users" }
127
167
  #
168
+ # You can also configure notification routes with scope like this:
169
+ # scope :myscope, as: :myscope do
170
+ # subscribed_by :users, routing_scope: :myscope
171
+ # end
172
+ # This routing_scope option creates the needed routes with specified scope like this:
173
+ # # Subscription routes
174
+ # myscope_user_subscriptions GET /myscope/users/:user_id/subscriptions(.:format)
175
+ # { controller:"activity_notification/subscriptions", action:"index", target_type:"users", routing_scope: :myscope }
176
+ # myscope_user_subscription GET /myscope/users/:user_id/subscriptions/:id(.:format)
177
+ # { controller:"activity_notification/subscriptions", action:"show", target_type:"users", routing_scope: :myscope }
178
+ # open_all_myscope_user_subscriptions POST /myscope/users/:user_id/subscriptions(.:format)
179
+ # { controller:"activity_notification/subscriptions", action:"create", target_type:"users", routing_scope: :myscope }
180
+ # myscope_user_subscription DELETE /myscope/users/:user_id/subscriptions/:id(.:format)
181
+ # { controller:"activity_notification/subscriptions", action:"destroy", target_type:"users", routing_scope: :myscope }
182
+ # subscribe_myscope_user_subscription POST /myscope/users/:user_id/subscriptions/:id/subscribe(.:format)
183
+ # { controller:"activity_notification/subscriptions", action:"subscribe", target_type:"users", routing_scope: :myscope }
184
+ # unsubscribe_myscope_user_subscription POST /myscope/users/:user_id/subscriptions/:id/unsubscribe(.:format)
185
+ # { controller:"activity_notification/subscriptions", action:"unsubscribe", target_type:"users", routing_scope: :myscope }
186
+ # subscribe_to_email_myscope_user_subscription POST /myscope/users/:user_id/subscriptions/:id/subscribe_to_email(.:format)
187
+ # { controller:"activity_notification/subscriptions", action:"subscribe_to_email", target_type:"users", routing_scope: :myscope }
188
+ # unsubscribe_to_email_myscope_user_subscription POST /myscope/users/:user_id/subscriptions/:id/unsubscribe_to_email(.:format)
189
+ # { controller:"activity_notification/subscriptions", action:"unsubscribe_to_email", target_type:"users", routing_scope: :myscope }
190
+ # subscribe_to_optional_target_myscope_user_subscription POST /myscope/users/:user_id/subscriptions/:id/subscribe_to_optional_target(.:format)
191
+ # { controller:"activity_notification/subscriptions", action:"subscribe_to_optional_target", target_type:"users", routing_scope: :myscope }
192
+ # unsubscribe_to_optional_target_myscope_user_subscription POST /myscope/users/:user_id/subscriptions/:id/unsubscribe_to_optional_target(.:format)
193
+ # { controller:"activity_notification/subscriptions", action:"unsubscribe_to_optional_target", target_type:"users", routing_scope: :myscope }
194
+ #
128
195
  # When you use devise authentication and you want make subscription targets assciated with devise,
129
196
  # you can create as follows in your routes:
130
- # notify_to :users, with_devise: :users
197
+ # subscribed_by :users, with_devise: :users
131
198
  # This with_devise option creates the needed routes assciated with devise authentication:
132
199
  # # Subscription with devise routes
133
200
  # user_subscriptions GET /users/:user_id/subscriptions(.:format)
@@ -151,6 +218,31 @@ module ActionDispatch::Routing
151
218
  # unsubscribe_to_optional_target_user_subscription POST /users/:user_id/subscriptions/:id/unsubscribe_to_optional_target(.:format)
152
219
  # { controller:"activity_notification/subscriptions_with_devise", action:"unsubscribe_to_optional_target", target_type:"users", devise_type:"users" }
153
220
  #
221
+ # When you use with_devise option and you want to make simple default routes as follows, you can use devise_default_routes option:
222
+ # subscribed_by :users, with_devise: :users, devise_default_routes: true
223
+ # These with_devise and devise_default_routes options create the needed routes assciated with authenticated devise resource as the default target
224
+ # # Subscription with devise routes
225
+ # user_subscriptions GET /subscriptions(.:format)
226
+ # { controller:"activity_notification/subscriptions_with_devise", action:"index", target_type:"users", devise_type:"users" }
227
+ # user_subscription GET /subscriptions/:id(.:format)
228
+ # { controller:"activity_notification/subscriptions_with_devise", action:"show", target_type:"users", devise_type:"users" }
229
+ # open_all_user_subscriptions POST /subscriptions(.:format)
230
+ # { controller:"activity_notification/subscriptions_with_devise", action:"create", target_type:"users", devise_type:"users" }
231
+ # user_subscription DELETE /subscriptions/:id(.:format)
232
+ # { controller:"activity_notification/subscriptions_with_devise", action:"destroy", target_type:"users", devise_type:"users" }
233
+ # subscribe_user_subscription POST /subscriptions/:id/subscribe(.:format)
234
+ # { controller:"activity_notification/subscriptions_with_devise", action:"subscribe", target_type:"users", devise_type:"users" }
235
+ # unsubscribe_user_subscription POST /subscriptions/:id/unsubscribe(.:format)
236
+ # { controller:"activity_notification/subscriptions_with_devise", action:"unsubscribe", target_type:"users", devise_type:"users" }
237
+ # subscribe_to_email_user_subscription POST /subscriptions/:id/subscribe_to_email(.:format)
238
+ # { controller:"activity_notification/subscriptions_with_devise", action:"subscribe_to_email", target_type:"users", devise_type:"users" }
239
+ # unsubscribe_to_email_user_subscription POST /subscriptions/:id/unsubscribe_to_email(.:format)
240
+ # { controller:"activity_notification/subscriptions_with_devise", action:"unsubscribe_to_email", target_type:"users", devise_type:"users" }
241
+ # subscribe_to_optional_target_user_subscription POST /subscriptions/:id/subscribe_to_optional_target(.:format)
242
+ # { controller:"activity_notification/subscriptions_with_devise", action:"subscribe_to_optional_target", target_type:"users", devise_type:"users" }
243
+ # unsubscribe_to_optional_target_user_subscription POST /subscriptions/:id/unsubscribe_to_optional_target(.:format)
244
+ # { controller:"activity_notification/subscriptions_with_devise", action:"unsubscribe_to_optional_target", target_type:"users", devise_type:"users" }
245
+ #
154
246
  # @example Define subscribed_by in config/routes.rb
155
247
  # subscribed_by :users
156
248
  # @example Define subscribed_by with options
@@ -160,29 +252,26 @@ module ActionDispatch::Routing
160
252
  #
161
253
  # @overload subscribed_by(*resources, *options)
162
254
  # @param [Symbol] resources Resources to notify
163
- # @option options [Symbol] :with_devise (false) Devise resources name for devise integration. Devise integration will be enabled by this option.
164
- # @option options [String] :model (:subscriptions) Model name of subscriptions
165
- # @option options [String] :controller ("activity_notification/subscriptions" | activity_notification/subscriptions_with_devise") :controller option as resources routing
166
- # @option options [Symbol] :as (nil) :as option as resources routing
167
- # @option options [Array] :only (nil) :only option as resources routing
168
- # @option options [Array] :except (nil) :except option as resources routing
255
+ # @option options [String] :routing_scope (nil) Routing scope for subscription routes
256
+ # @option options [Symbol] :with_devise (false) Devise resources name for devise integration. Devise integration will be enabled by this option.
257
+ # @option options [Boolean] :devise_default_routes (false) Whether you will create routes as device default routes assciated with authenticated devise resource as the default target
258
+ # @option options [String] :model (:subscriptions) Model name of subscriptions
259
+ # @option options [String] :controller ("activity_notification/subscriptions" | activity_notification/subscriptions_with_devise") :controller option as resources routing
260
+ # @option options [Symbol] :as (nil) :as option as resources routing
261
+ # @option options [Array] :only (nil) :only option as resources routing
262
+ # @option options [Array] :except (nil) :except option as resources routing
169
263
  # @return [ActionDispatch::Routing::Mapper] Routing mapper instance
170
264
  def subscribed_by(*resources)
171
265
  options = create_options(:subscriptions, resources.extract_options!, [:new, :edit, :update])
172
266
 
173
267
  resources.each do |target|
174
- self.resources target, only: :none do
175
- options[:defaults] = { target_type: target.to_s }.merge(options[:devise_defaults])
176
- resources_options = options.select { |key, _| [:with_devise, :model, :devise_defaults].exclude? key }
177
- self.resources options[:model], resources_options do
178
- member do
179
- post :subscribe unless ignore_path?(:subscribe, options)
180
- post :unsubscribe unless ignore_path?(:unsubscribe, options)
181
- post :subscribe_to_email unless ignore_path?(:subscribe_to_email, options)
182
- post :unsubscribe_to_email unless ignore_path?(:unsubscribe_to_email, options)
183
- post :subscribe_to_optional_target unless ignore_path?(:subscribe_to_optional_target, options)
184
- post :unsubscribe_to_optional_target unless ignore_path?(:unsubscribe_to_optional_target, options)
185
- end
268
+ options[:defaults] = { target_type: target.to_s }.merge(options[:devise_defaults])
269
+ resources_options = options.select { |key, _| [:with_devise, :devise_default_routes, :model, :devise_defaults].exclude? key }
270
+ if options[:with_devise].present? && options[:devise_default_routes].present?
271
+ create_subscription_routes options, resources_options
272
+ else
273
+ self.resources target, only: :none do
274
+ create_subscription_routes options, resources_options
186
275
  end
187
276
  end
188
277
  end
@@ -202,14 +291,16 @@ module ActionDispatch::Routing
202
291
  false
203
292
  end
204
293
 
205
- # Create options fo routing
294
+ # Create options for routing
206
295
  # @api private
207
296
  # @todo Check resources if it includes target module
208
297
  # @todo Check devise configuration in model
209
298
  # @todo Support other options like :as, :path_prefix, :path_names ...
210
299
  #
211
300
  # @param [Symbol] resource Name of the resource model
212
- # @return [Boolean] Whether action path is ignored
301
+ # @param [Hash] options Passed options from notify_to or subscribed_by
302
+ # @param [Hash] except_actions Actions in [:index, :show, :new, :create, :edit, :update, :destroy] to remove routes
303
+ # @return [Hash] Options to create routes
213
304
  def create_options(resource, options = {}, except_actions = [])
214
305
  # Check resources if it includes target module
215
306
  resources_name = resource.to_s.pluralize.underscore
@@ -219,6 +310,7 @@ module ActionDispatch::Routing
219
310
  options[:as] ||= resources_name
220
311
  # Check devise configuration in model
221
312
  options[:devise_defaults] = { devise_type: options[:with_devise].to_s }
313
+ options[:devise_defaults] = options[:devise_defaults].merge(options.slice(:devise_default_routes))
222
314
  else
223
315
  options[:controller] ||= "activity_notification/#{resources_name}"
224
316
  options[:devise_defaults] = {}
@@ -226,11 +318,48 @@ module ActionDispatch::Routing
226
318
  (options[:except] ||= []).concat(except_actions)
227
319
  if options[:with_subscription].present?
228
320
  options[:subscription_option] = (options[:with_subscription].is_a?(Hash) ? options[:with_subscription] : {})
229
- .merge(with_devise: options[:with_devise])
321
+ .merge(options.slice(:with_devise, :devise_default_routes, :routing_scope))
230
322
  end
231
323
  # Support other options like :as, :path_prefix, :path_names ...
232
324
  options
233
325
  end
234
326
 
327
+ # Create routes for notifications
328
+ # @api private
329
+ #
330
+ # @param [Symbol] resource Name of the resource model
331
+ # @param [Hash] options Passed options from notify_to
332
+ # @param [Hash] resources_options Options to send resources method
333
+ def create_notification_routes(options = {}, resources_options = [])
334
+ self.resources options[:model], resources_options do
335
+ collection do
336
+ post :open_all unless ignore_path?(:open_all, options)
337
+ end
338
+ member do
339
+ get :move unless ignore_path?(:move, options)
340
+ post :open unless ignore_path?(:open, options)
341
+ end
342
+ end
343
+ end
344
+
345
+ # Create routes for subscriptions
346
+ # @api private
347
+ #
348
+ # @param [Symbol] resource Name of the resource model
349
+ # @param [Hash] options Passed options from subscribed_by
350
+ # @param [Hash] resources_options Options to send resources method
351
+ def create_subscription_routes(options = {}, resources_options = [])
352
+ self.resources options[:model], resources_options do
353
+ member do
354
+ post :subscribe unless ignore_path?(:subscribe, options)
355
+ post :unsubscribe unless ignore_path?(:unsubscribe, options)
356
+ post :subscribe_to_email unless ignore_path?(:subscribe_to_email, options)
357
+ post :unsubscribe_to_email unless ignore_path?(:unsubscribe_to_email, options)
358
+ post :subscribe_to_optional_target unless ignore_path?(:subscribe_to_optional_target, options)
359
+ post :unsubscribe_to_optional_target unless ignore_path?(:unsubscribe_to_optional_target, options)
360
+ end
361
+ end
362
+ end
363
+
235
364
  end
236
365
  end