activity_notification 1.7.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +3 -0
  3. data/.travis.yml +16 -2
  4. data/CHANGELOG.md +22 -2
  5. data/Gemfile +7 -0
  6. data/Procfile +2 -0
  7. data/README.md +366 -32
  8. data/Rakefile +19 -10
  9. data/activity_notification.gemspec +5 -3
  10. data/app/channels/activity_notification/notification_channel.rb +37 -0
  11. data/app/channels/activity_notification/notification_with_devise_channel.rb +51 -0
  12. data/app/controllers/activity_notification/notifications_controller.rb +1 -1
  13. data/app/controllers/activity_notification/subscriptions_controller.rb +1 -1
  14. data/app/jobs/activity_notification/notify_all_job.rb +16 -0
  15. data/app/jobs/activity_notification/notify_job.rb +17 -0
  16. data/app/jobs/activity_notification/notify_to_job.rb +16 -0
  17. data/app/views/activity_notification/notifications/default/_default_without_grouping.html.erb +1 -1
  18. data/app/views/activity_notification/notifications/default/index.html.erb +55 -2
  19. data/bin/_dynamodblocal +4 -0
  20. data/{scripts → bin}/bundle_update.sh +1 -0
  21. data/bin/deploy_on_heroku.sh +14 -0
  22. data/bin/install_dynamodblocal.sh +5 -0
  23. data/bin/start_dynamodblocal.sh +47 -0
  24. data/bin/stop_dynamodblocal.sh +34 -0
  25. data/gemfiles/Gemfile.rails-4.2 +1 -0
  26. data/gemfiles/Gemfile.rails-5.0 +2 -0
  27. data/gemfiles/Gemfile.rails-5.1 +1 -0
  28. data/gemfiles/Gemfile.rails-5.2 +1 -0
  29. data/gemfiles/Gemfile.rails-6.0.rc +21 -0
  30. data/lib/activity_notification.rb +1 -0
  31. data/lib/activity_notification/apis/notification_api.rb +289 -136
  32. data/lib/activity_notification/apis/subscription_api.rb +80 -53
  33. data/lib/activity_notification/common.rb +3 -3
  34. data/lib/activity_notification/config.rb +89 -33
  35. data/lib/activity_notification/controllers/common_controller.rb +19 -7
  36. data/lib/activity_notification/helpers/errors.rb +4 -0
  37. data/lib/activity_notification/helpers/view_helpers.rb +1 -1
  38. data/lib/activity_notification/models/concerns/notifiable.rb +61 -53
  39. data/lib/activity_notification/models/concerns/subscriber.rb +7 -6
  40. data/lib/activity_notification/models/concerns/target.rb +73 -28
  41. data/lib/activity_notification/optional_targets/base.rb +2 -2
  42. data/lib/activity_notification/orm/active_record/notification.rb +4 -23
  43. data/lib/activity_notification/orm/dynamoid.rb +495 -0
  44. data/lib/activity_notification/orm/dynamoid/extension.rb +184 -0
  45. data/lib/activity_notification/orm/dynamoid/notification.rb +189 -0
  46. data/lib/activity_notification/orm/dynamoid/subscription.rb +82 -0
  47. data/lib/activity_notification/orm/mongoid.rb +4 -1
  48. data/lib/activity_notification/orm/mongoid/notification.rb +8 -25
  49. data/lib/activity_notification/orm/mongoid/subscription.rb +1 -1
  50. data/lib/activity_notification/roles/acts_as_notifiable.rb +33 -5
  51. data/lib/activity_notification/roles/acts_as_target.rb +62 -9
  52. data/lib/activity_notification/version.rb +1 -1
  53. data/lib/generators/templates/activity_notification.rb +30 -7
  54. data/lib/tasks/activity_notification_tasks.rake +14 -4
  55. data/spec/channels/notification_channel_shared_examples.rb +59 -0
  56. data/spec/channels/notification_channel_spec.rb +50 -0
  57. data/spec/channels/notification_with_devise_channel_spec.rb +99 -0
  58. data/spec/concerns/apis/notification_api_spec.rb +2 -2
  59. data/spec/concerns/apis/subscription_api_spec.rb +2 -2
  60. data/spec/concerns/models/notifiable_spec.rb +72 -7
  61. data/spec/concerns/models/subscriber_spec.rb +53 -49
  62. data/spec/concerns/models/target_spec.rb +135 -13
  63. data/spec/config_spec.rb +41 -1
  64. data/spec/controllers/notifications_controller_shared_examples.rb +7 -3
  65. data/spec/controllers/subscriptions_controller_shared_examples.rb +7 -3
  66. data/spec/helpers/view_helpers_spec.rb +12 -10
  67. data/spec/models/dummy/dummy_group_spec.rb +4 -0
  68. data/spec/models/dummy/dummy_notifiable_spec.rb +4 -0
  69. data/spec/models/dummy/dummy_notifier_spec.rb +4 -0
  70. data/spec/models/dummy/dummy_subscriber_spec.rb +3 -0
  71. data/spec/models/dummy/dummy_target_spec.rb +4 -0
  72. data/spec/models/notification_spec.rb +164 -45
  73. data/spec/models/subscription_spec.rb +69 -14
  74. data/spec/orm/dynamoid_spec.rb +115 -0
  75. data/spec/rails_app/app/assets/javascripts/application.js +2 -1
  76. data/spec/rails_app/app/assets/javascripts/cable.js +12 -0
  77. data/spec/rails_app/app/controllers/comments_controller.rb +3 -4
  78. data/spec/rails_app/app/models/admin.rb +6 -4
  79. data/spec/rails_app/app/models/article.rb +2 -2
  80. data/spec/rails_app/app/models/comment.rb +17 -5
  81. data/spec/rails_app/app/models/user.rb +5 -3
  82. data/spec/rails_app/app/views/activity_notification/notifications/users/overridden/custom/_test.html.erb +1 -0
  83. data/spec/rails_app/config/application.rb +6 -1
  84. data/spec/rails_app/config/cable.yml +8 -0
  85. data/spec/rails_app/config/dynamoid.rb +5 -0
  86. data/spec/rails_app/config/environment.rb +4 -1
  87. data/spec/rails_app/config/environments/production.rb +1 -1
  88. data/spec/rails_app/config/initializers/activity_notification.rb +30 -7
  89. data/spec/rails_app/config/locales/activity_notification.en.yml +2 -0
  90. data/spec/rails_app/db/seeds.rb +21 -5
  91. data/spec/rails_app/lib/mailer_previews/mailer_preview.rb +12 -4
  92. data/spec/roles/acts_as_notifiable_spec.rb +2 -2
  93. data/spec/roles/acts_as_target_spec.rb +1 -1
  94. data/spec/spec_helper.rb +15 -8
  95. metadata +67 -20
  96. data/spec/rails_app/app/models/.keep +0 -0
  97. data/spec/rails_app/app/views/activity_notification/notifications/users/overriden/custom/_test.html.erb +0 -1
@@ -8,7 +8,7 @@ module ActivityNotification
8
8
  # @param [String] name Association name
9
9
  # @param [Object] instance Associated instance
10
10
  # @return [Mongoid::Criteria<Notificaion>] Database query of filtered notifications
11
- scope :filtered_by_association, ->(name, instance) { instance.present? ? where({ "#{name}_id" => instance.id, "#{name}_type" => instance.class.name }) : none }
11
+ scope :filtered_by_association, ->(name, instance) { where("#{name}_id" => instance.present? ? instance.id : nil, "#{name}_type" => instance.present? ? instance.class.name : nil) }
12
12
  end
13
13
 
14
14
  class_methods do
@@ -24,6 +24,8 @@ module ActivityNotification
24
24
  id_field, type_field = "#{association_name}_id", "#{association_name}_type"
25
25
  field id_field, type: String
26
26
  field type_field, type: String
27
+ associated_record_field = "#{association_name}_record"
28
+ field associated_record_field, type: String if ActivityNotification.config.store_with_associated_records && _options[:store_with_associated_records]
27
29
 
28
30
  self.instance_eval do
29
31
  define_method(name) do |reload = false|
@@ -41,6 +43,7 @@ module ActivityNotification
41
43
  if new_instance.nil? then instance_id, instance_type = nil, nil else instance_id, instance_type = new_instance.id, new_instance.class.name end
42
44
  self.send("#{id_field}=", instance_id)
43
45
  self.send("#{type_field}=", instance_type)
46
+ self.send("#{associated_record_field}=", new_instance.to_json) if ActivityNotification.config.store_with_associated_records && _options[:store_with_associated_records]
44
47
  self.instance_variable_set("@#{name}", nil)
45
48
  end
46
49
  end
@@ -19,12 +19,12 @@ module ActivityNotification
19
19
  # Belongs to target instance of this notification as polymorphic association.
20
20
  # @scope instance
21
21
  # @return [Object] Target instance of this notification
22
- belongs_to_polymorphic_xdb_record :target
22
+ belongs_to_polymorphic_xdb_record :target, store_with_associated_records: true
23
23
 
24
24
  # Belongs to notifiable instance of this notification as polymorphic association.
25
25
  # @scope instance
26
26
  # @return [Object] Notifiable instance of this notification
27
- belongs_to_polymorphic_xdb_record :notifiable
27
+ belongs_to_polymorphic_xdb_record :notifiable, store_with_associated_records: true
28
28
 
29
29
  # Belongs to group instance of this notification as polymorphic association.
30
30
  # @scope instance
@@ -53,7 +53,7 @@ module ActivityNotification
53
53
  # Belongs to :otifier instance of this notification.
54
54
  # @scope instance
55
55
  # @return [Object] Notifier instance of this notification
56
- belongs_to_polymorphic_xdb_record :notifier
56
+ belongs_to_polymorphic_xdb_record :notifier, store_with_associated_records: true
57
57
 
58
58
  validates :target, presence: true
59
59
  validates :notifiable, presence: true
@@ -170,26 +170,6 @@ module ActivityNotification
170
170
  # Dummy reload method for test of notifications.
171
171
  scope :reload, -> { }
172
172
 
173
- # Returns latest notification instance.
174
- # @return [Notification] Latest notification instance
175
- def self.latest
176
- latest_order.first
177
- end
178
-
179
- # Returns earliest notification instance.
180
- # @return [Notification] Earliest notification instance
181
- def self.earliest
182
- earliest_order.first
183
- end
184
-
185
- # Selects unique keys from query for notifications.
186
- # @return [Array<String>] Array of notification unique keys
187
- def self.uniq_keys
188
- # distinct method cannot keep original sort
189
- # distinct(:key)
190
- pluck(:key).uniq
191
- end
192
-
193
173
  # Returns if the notification is group owner.
194
174
  # Calls NotificationApi#group_owner? as super method.
195
175
  # @return [Boolean] If the notification is group owner
@@ -197,9 +177,12 @@ module ActivityNotification
197
177
  super
198
178
  end
199
179
 
200
- # Raise DeleteRestrictionError for notifications.
180
+ # Raise ActivityNotification::DeleteRestrictionError for notifications.
181
+ # @param [String] error_text Error text for raised exception
182
+ # @raise ActivityNotification::DeleteRestrictionError
183
+ # @return [void]
201
184
  def self.raise_delete_restriction_error(error_text)
202
- raise error_text
185
+ raise ActivityNotification::DeleteRestrictionError, error_text
203
186
  end
204
187
 
205
188
  protected
@@ -26,7 +26,7 @@ module ActivityNotification
26
26
  field :subscribed_to_email_at, type: DateTime
27
27
  field :unsubscribed_to_email_at, type: DateTime
28
28
  field :optional_targets, type: Hash, default: {}
29
-
29
+
30
30
  validates :target, presence: true
31
31
  validates :key, presence: true
32
32
  validates_inclusion_of :subscribing, in: [true, false]
@@ -95,6 +95,18 @@ module ActivityNotification
95
95
  # acts_as_notifiable :users, targets: User.all, email_allowed: true
96
96
  # end
97
97
  #
98
+ # * :action_cable_allowed
99
+ # * Whether activity_notification publishes notifications to ActionCable channel.
100
+ # Specified method or symbol is expected to return true (not nil) or false (nil).
101
+ # This parameter is a optional since default value is false.
102
+ # To use ActionCable for notifications, action_cable_allowed option must return true (not nil) in both of notifiable and target model.
103
+ # This can be also configured default option in initializer.
104
+ # @example Enable notification ActionCable for this notifiable model
105
+ # # app/models/comment.rb
106
+ # class Comment < ActiveRecord::Base
107
+ # acts_as_notifiable :users, targets: User.all, action_cable_allowed: true
108
+ # end
109
+ #
98
110
  # * :notifiable_path
99
111
  # * Path to redirect from open or move action of notification controller.
100
112
  # You can also use this notifiable_path as notifiable link in notification view.
@@ -196,6 +208,7 @@ module ActivityNotification
196
208
  # @option options [Symbol, Proc, Object] :notifier (nil) Notifier of the notifications
197
209
  # @option options [Symbol, Proc, Hash] :parameters ({}) Additional parameters of the notifications
198
210
  # @option options [Symbol, Proc, Boolean] :email_allowed (ActivityNotification.config.email_enabled) Whether activity_notification sends notification email
211
+ # @option options [Symbol, Proc, Boolean] :action_cable_allowed (ActivityNotification.config.action_cable_enabled) Whether activity_notification publishes WebSocket using ActionCable
199
212
  # @option options [Symbol, Proc, String] :notifiable_path (polymorphic_path(self)) Path to redirect from open or move action of notification controller
200
213
  # @option options [Boolean, Hash] :tracked (nil) Flag or parameters for automatic tracked notifications
201
214
  # @option options [Symbol, Proc, String] :printable_name (ActivityNotification::Common.printable_name) Printable notifiable name
@@ -220,7 +233,7 @@ module ActivityNotification
220
233
 
221
234
  options[:printable_notifiable_name] ||= options.delete(:printable_name)
222
235
  configured_params
223
- .merge set_acts_as_parameters_for_target(target_type, [:targets, :group, :group_expiry_delay, :parameters, :email_allowed], options, "notification_")
236
+ .merge set_acts_as_parameters_for_target(target_type, [:targets, :group, :group_expiry_delay, :parameters, :email_allowed, :action_cable_allowed], options, "notification_")
224
237
  .merge set_acts_as_parameters_for_target(target_type, [:notifier, :notifiable_path, :printable_notifiable_name, :optional_targets], options)
225
238
  end
226
239
 
@@ -233,6 +246,7 @@ module ActivityNotification
233
246
  :notifier,
234
247
  :parameters,
235
248
  :email_allowed,
249
+ :action_cable_allowed,
236
250
  :notifiable_path,
237
251
  :printable_notifiable_name, :printable_name,
238
252
  :dependent_notifications,
@@ -284,11 +298,22 @@ module ActivityNotification
284
298
  # See the followings:
285
299
  # https://github.com/rails/rails/issues/30779
286
300
  # https://github.com/rails/rails/pull/32167
287
- # :only-rails-without-callback-issue:
301
+
302
+ # :only-rails5-plus#only-rails-without-callback-issue:
303
+ # :only-rails5-plus#only-rails-without-callback-issue#except-dynamoid:
304
+ # :except-rails5-plus#only-rails-without-callback-issue:
305
+ # :except-rails5-plus#only-rails-without-callback-issue#except-dynamoid:
288
306
  if !(Gem::Version.new("5.1.6") <= Rails.gem_version && Rails.gem_version < Gem::Version.new("5.2.2")) && respond_to?(:after_commit)
289
307
  after_commit tracked_proc, on: tracked_action
290
- # :only-rails-without-callback-issue:
291
- # :only-rails-with-callback-issue:
308
+ # :only-rails5-plus#only-rails-without-callback-issue:
309
+ # :only-rails5-plus#only-rails-without-callback-issue#except-dynamoid:
310
+ # :except-rails5-plus#only-rails-without-callback-issue:
311
+ # :except-rails5-plus#only-rails-without-callback-issue#except-dynamoid:
312
+
313
+ # :only-rails5-plus#only-rails-with-callback-issue:
314
+ # :only-rails5-plus#only-rails-with-callback-issue#except-dynamoid:
315
+ # :except-rails5-plus#only-rails-with-callback-issue:
316
+ # :except-rails5-plus#only-rails-with-callback-issue#except-dynamoid:
292
317
  else
293
318
  case tracked_action
294
319
  when :create
@@ -297,7 +322,10 @@ module ActivityNotification
297
322
  after_update tracked_proc
298
323
  end
299
324
  end
300
- # :only-rails-with-callback-issue:
325
+ # :only-rails5-plus#only-rails-with-callback-issue:
326
+ # :only-rails5-plus#only-rails-with-callback-issue#except-dynamoid:
327
+ # :except-rails5-plus#only-rails-with-callback-issue:
328
+ # :except-rails5-plus#only-rails-with-callback-issue#except-dynamoid:
301
329
  end
302
330
 
303
331
  # Adds destroy dependency.
@@ -34,6 +34,57 @@ module ActivityNotification
34
34
  # acts_as_target email: :email, email_allowed: :confirmed_at
35
35
  # end
36
36
  #
37
+ # * :batch_email_allowed
38
+ # * Whether activity_notification sends batch notification email to this target.
39
+ # Specified method or symbol is expected to return true (not nil) or false (nil).
40
+ # This parameter is a optional since default value is false.
41
+ # To use batch notification email, both of batch_email_allowed and subscription_allowed options must return true (not nil) in target model.
42
+ # This can be also configured default option in initializer.
43
+ # @example Always enable batch email notification for this target
44
+ # # app/models/user.rb
45
+ # class User < ActiveRecord::Base
46
+ # acts_as_target email: :email, batch_email_allowed: true
47
+ # end
48
+ # @example Use confirmed_at of devise field to decide whether activity_notification sends batch notification email to this user
49
+ # # app/models/user.rb
50
+ # class User < ActiveRecord::Base
51
+ # acts_as_target email: :email, batch_email_allowed: :confirmed_at
52
+ # end
53
+ #
54
+ # * :subscription_allowed
55
+ # * Whether activity_notification manages subscriptions of this target.
56
+ # Specified method or symbol is expected to return true (not nil) or false (nil).
57
+ # This parameter is a optional since default value is false.
58
+ # This can be also configured default option in initializer.
59
+ # @example Subscribe notifications for this target
60
+ # # app/models/user.rb
61
+ # class User < ActiveRecord::Base
62
+ # acts_as_target subscription_allowed: true
63
+ # end
64
+ #
65
+ # * :action_cable_allowed
66
+ # * Whether activity_notification publishes WebSocket notifications using ActionCable to this target.
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 ActionCable for notifications, action_cable_enabled 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 notification ActionCable for this target
72
+ # # app/models/user.rb
73
+ # class User < ActiveRecord::Base
74
+ # acts_as_target action_cable_allowed: true
75
+ # end
76
+ #
77
+ # * :action_cable_with_devise
78
+ # * Whether activity_notification publishes WebSocket notifications using ActionCable only to authenticated target with Devise.
79
+ # Specified method or symbol is expected to return true (not nil) or false (nil).
80
+ # This parameter is a optional since default value is false.
81
+ # To use ActionCable for notifications, also action_cable_enabled option must return true (not nil) in the target model.
82
+ # @example Enable notification ActionCable for this target
83
+ # # app/models/user.rb
84
+ # class User < ActiveRecord::Base
85
+ # acts_as_target action_cable_allowed: true, action_cable_with_devise* true
86
+ # end
87
+ #
37
88
  # * :devise_resource
38
89
  # * Integrated resource with devise authentication.
39
90
  # This parameter is a optional since `self` is used as default value.
@@ -121,20 +172,22 @@ module ActivityNotification
121
172
  # end
122
173
  #
123
174
  # @param [Hash] options Options for notifiable model configuration
124
- # @option options [Symbol, Proc, String] :email (nil) Email address to send notification email
125
- # @option options [Symbol, Proc, Boolean] :email_allowed (ActivityNotification.config.email_enabled) Whether activity_notification sends notification email to this target
126
- # @option options [Symbol, Proc, Boolean] :batch_email_allowed (ActivityNotification.config.email_enabled) Whether activity_notification sends batch notification email to this target
127
- # @option options [Symbol, Proc, Boolean] :subscription_allowed (ActivityNotification.config.subscription_enabled) Whether activity_notification manages subscriptions of this target
128
- # @option options [Symbol, Proc, Object] :devise_resource (->(model) { model }) Integrated resource with devise authentication
129
- # @option options [Symbol, Proc, Object] :current_devise_target (->(current_resource) { current_resource }) Current authenticated target by devise authentication
130
- # @option options [Symbol, Proc, String] :printable_name (ActivityNotification::Common.printable_name) Printable notification target name
175
+ # @option options [Symbol, Proc, String] :email (nil) Email address to send notification email
176
+ # @option options [Symbol, Proc, Boolean] :email_allowed (ActivityNotification.config.email_enabled) Whether activity_notification sends notification email to this target
177
+ # @option options [Symbol, Proc, Boolean] :batch_email_allowed (ActivityNotification.config.email_enabled) Whether activity_notification sends batch notification email to this target
178
+ # @option options [Symbol, Proc, Boolean] :subscription_allowed (ActivityNotification.config.subscription_enabled) Whether activity_notification manages subscriptions of this target
179
+ # @option options [Symbol, Proc, Boolean] :action_cable_allowed (ActivityNotification.config.action_cable_enabled) Whether activity_notification publishes WebSocket notifications using ActionCable to this target
180
+ # @option options [Symbol, Proc, Boolean] :action_cable_with_devise (false) Whether activity_notification publishes WebSocket notifications using ActionCable only to authenticated target with Devise
181
+ # @option options [Symbol, Proc, Object] :devise_resource (->(model) { model }) Integrated resource with devise authentication
182
+ # @option options [Symbol, Proc, Object] :current_devise_target (->(current_resource) { current_resource }) Current authenticated target by devise authentication
183
+ # @option options [Symbol, Proc, String] :printable_name (ActivityNotification::Common.printable_name) Printable notification target name
131
184
  # @return [Hash] Configured parameters as target model
132
185
  def acts_as_target(options = {})
133
186
  include Target
134
187
 
135
188
  options[:printable_notification_target_name] ||= options.delete(:printable_name)
136
189
  options[:batch_notification_email_allowed] ||= options.delete(:batch_email_allowed)
137
- acts_as_params = set_acts_as_parameters([:email, :email_allowed, :subscription_allowed, :devise_resource, :current_devise_target], options, "notification_")
190
+ acts_as_params = set_acts_as_parameters([:email, :email_allowed, :subscription_allowed, :action_cable_allowed, :action_cable_with_devise, :devise_resource, :current_devise_target], options, "notification_")
138
191
  .merge set_acts_as_parameters([:batch_notification_email_allowed, :printable_notification_target_name], options)
139
192
  include Subscriber if subscription_enabled?
140
193
  acts_as_params
@@ -144,7 +197,7 @@ module ActivityNotification
144
197
  # Returns array of available target options in acts_as_target.
145
198
  # @return [Array<Symbol>] Array of available target options
146
199
  def available_target_options
147
- [:email, :email_allowed, :batch_email_allowed, :subscription_allowed, :devise_resource, :printable_notification_target_name, :printable_name].freeze
200
+ [:email, :email_allowed, :batch_email_allowed, :subscription_allowed, :action_cable_enabled, :action_cable_with_devise, :devise_resource, :printable_notification_target_name, :printable_name].freeze
148
201
  end
149
202
  end
150
203
  end
@@ -1,3 +1,3 @@
1
1
  module ActivityNotification
2
- VERSION = "1.7.1"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -1,14 +1,14 @@
1
1
  ActivityNotification.configure do |config|
2
2
 
3
- # Configure ORM name for ActivityNotification.
4
- # Set :active_record or :mongoid.
5
- ENV['AN_ORM'] = 'active_record' unless ENV['AN_ORM'] == 'mongoid'
6
- config.orm = ENV['AN_ORM']
7
-
8
- # Configure if all activity notifications are enabled.
9
- # Set false when you want to turn off activity notifications.
3
+ # Configure if all activity notifications are enabled
4
+ # Set false when you want to turn off activity notifications
10
5
  config.enabled = true
11
6
 
7
+ # Configure ORM name for ActivityNotification.
8
+ # Set :active_record, :mongoid or :dynamoid.
9
+ ENV['AN_ORM'] = 'active_record' if ['mongoid', 'dynamoid'].exclude?(ENV['AN_ORM'])
10
+ config.orm = ENV['AN_ORM'].to_sym
11
+
12
12
  # Configure table name to store notification data.
13
13
  config.notification_table_name = "notifications"
14
14
 
@@ -47,6 +47,9 @@ ActivityNotification.configure do |config|
47
47
  # Configure the parent class for activity_notification controllers.
48
48
  # config.parent_controller = 'ApplicationController'
49
49
 
50
+ # Configure the parent class for activity_notification channels.
51
+ # config.parent_channel = 'ActionCable::Channel::Base'
52
+
50
53
  # Configure the custom mailer templates directory
51
54
  # config.mailer_templates_dir = 'activity_notification/mailer'
52
55
 
@@ -56,4 +59,24 @@ ActivityNotification.configure do |config|
56
59
  # Configure ActiveJob queue name for delayed notifications.
57
60
  config.active_job_queue = :activity_notification
58
61
 
62
+ # Configure delimiter of composite key for DynamoDB.
63
+ # config.composite_key_delimiter = '#'
64
+
65
+ # Configure if activity_notification stores notificaion records including associated records like target and notifiable..
66
+ # This store_with_associated_records option can be set true only when you use mongoid or dynamoid ORM.
67
+ config.store_with_associated_records = false
68
+
69
+ # Configure if WebSocket subscription using ActionCable is enabled.
70
+ # Note that you can configure them for each model by acts_as roles.
71
+ # Set true when you want to turn on WebSocket subscription using ActionCable as default.
72
+ config.action_cable_enabled = false
73
+
74
+ # Configure if ctivity_notification publishes WebSocket notifications using ActionCable only to authenticated target with Devise.
75
+ # Note that you can configure them for each model by acts_as roles.
76
+ # Set true when you want to use Device integration with WebSocket subscription using ActionCable as default.
77
+ config.action_cable_with_devise = false
78
+
79
+ # Configure notification channel prefix for ActionCable.
80
+ config.notification_channel_prefix = 'activity_notification_channel'
81
+
59
82
  end
@@ -1,4 +1,14 @@
1
- # desc "Explaining what the task does"
2
- # task :activity_notification do
3
- # # Task goes here
4
- # end
1
+ namespace :activity_notification do
2
+ desc "Create Amazon DynamoDB tables used by activity_notification with Dynamoid"
3
+ task create_dynamodb_tables: :environment do
4
+ if ActivityNotification.config.orm == :dynamoid
5
+ ActivityNotification::Notification.create_table(sync: true)
6
+ puts "Created table: #{ActivityNotification::Notification.table_name}"
7
+ ActivityNotification::Subscription.create_table(sync: true)
8
+ puts "Created table: #{ActivityNotification::Subscription.table_name}"
9
+ else
10
+ puts "Error: ActivityNotification.config.orm is not set to :dynamoid."
11
+ puts "Error: Confirm to set AN_ORM environment variable to dynamoid or set ActivityNotification.config.orm to :dynamoid."
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,59 @@
1
+ # @See https://github.com/palkan/action-cable-testing
2
+ shared_examples_for :notification_channel do
3
+ let(:target_params) { { target_type: target_type }.merge(extra_params || {}) }
4
+
5
+ before { stub_connection }
6
+
7
+ context "with target_type and target_id parameters" do
8
+ it "successfully subscribes" do
9
+ subscribe(target_params.merge({ target_id: test_target.id, typed_target_param => 'dummy' }))
10
+ expect(subscription).to be_confirmed
11
+ expect(subscription).to have_stream_from("#{ActivityNotification.config.notification_channel_prefix}_#{test_target.to_class_name}#{ActivityNotification.config.composite_key_delimiter}#{test_target.id}")
12
+ end
13
+ end
14
+
15
+ context "with target_type and (typed_target)_id parameters" do
16
+ it "successfully subscribes" do
17
+ subscribe(target_params.merge({ typed_target_param => test_target.id }))
18
+ expect(subscription).to be_confirmed
19
+ expect(subscription).to have_stream_from("#{ActivityNotification.config.notification_channel_prefix}_#{test_target.to_class_name}#{ActivityNotification.config.composite_key_delimiter}#{test_target.id}")
20
+ end
21
+ end
22
+
23
+ context "without any parameters" do
24
+ it "rejects subscription" do
25
+ subscribe
26
+ expect(subscription).to be_rejected
27
+ expect {
28
+ expect(subscription).to have_stream_from("#{ActivityNotification.config.notification_channel_prefix}_#{test_target.to_class_name}#{ActivityNotification.config.composite_key_delimiter}#{test_target.id}")
29
+ }.to raise_error(/Must be subscribed!/)
30
+ end
31
+ end
32
+
33
+ context "without target_type parameter" do
34
+ it "rejects subscription" do
35
+ subscribe({ typed_target_param => test_target.id })
36
+ expect(subscription).to be_rejected
37
+ expect {
38
+ expect(subscription).to have_stream_from("#{ActivityNotification.config.notification_channel_prefix}_#{test_target.to_class_name}#{ActivityNotification.config.composite_key_delimiter}#{test_target.id}")
39
+ }.to raise_error(/Must be subscribed!/)
40
+ end
41
+ end
42
+
43
+ context "without target_id and (typed_target)_id parameters" do
44
+ it "rejects subscription" do
45
+ subscribe(target_params)
46
+ expect(subscription).to be_rejected
47
+ end
48
+ end
49
+
50
+ context "with not found (typed_target)_id parameter" do
51
+ it "rejects subscription" do
52
+ subscribe(target_params.merge({ typed_target_param => 0 }))
53
+ expect(subscription).to be_rejected
54
+ expect {
55
+ expect(subscription).to have_stream_from("#{ActivityNotification.config.notification_channel_prefix}_#{test_target.to_class_name}#{ActivityNotification.config.composite_key_delimiter}#{test_target.id}")
56
+ }.to raise_error(/Must be subscribed!/)
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,50 @@
1
+ if Rails::VERSION::MAJOR >= 5
2
+ require 'channels/notification_channel_shared_examples'
3
+
4
+ # @See https://github.com/palkan/action-cable-testing
5
+ describe ActivityNotification::NotificationChannel, type: :channel do
6
+ let(:test_target) { create(:user) }
7
+ let(:target_type) { "User" }
8
+ let(:typed_target_param) { "user_id" }
9
+ let(:extra_params) { {} }
10
+
11
+ context "when target.notification_action_cable_with_devise? returns true" do
12
+ before do
13
+ @user_notification_action_cable_with_devise = User._notification_action_cable_with_devise
14
+ User._notification_action_cable_with_devise = true
15
+ end
16
+
17
+ after do
18
+ User._notification_action_cable_with_devise = @user_notification_action_cable_with_devise
19
+ end
20
+
21
+ it "rejects subscription even if target_type and target_id parameters are passed" do
22
+ subscribe({ target_type: target_type, target_id: test_target.id })
23
+ expect(subscription).to be_rejected
24
+ expect {
25
+ expect(subscription).to have_stream_from("#{ActivityNotification.config.notification_channel_prefix}_#{test_target.to_class_name}#{ActivityNotification.config.composite_key_delimiter}#{test_target.id}")
26
+ }.to raise_error(/Must be subscribed!/)
27
+ end
28
+ end
29
+
30
+ context "when target.notification_action_cable_with_devise? returns false" do
31
+ before do
32
+ @user_notification_action_cable_with_devise = User._notification_action_cable_with_devise
33
+ User._notification_action_cable_with_devise = false
34
+ end
35
+
36
+ after do
37
+ User._notification_action_cable_with_devise = @user_notification_action_cable_with_devise
38
+ end
39
+
40
+ it "successfully subscribes with target_type and target_id parameters" do
41
+ subscribe({ target_type: target_type, target_id: test_target.id })
42
+ expect(subscription).to be_confirmed
43
+ expect(subscription).to have_stream_from("#{ActivityNotification.config.notification_channel_prefix}_#{test_target.to_class_name}#{ActivityNotification.config.composite_key_delimiter}#{test_target.id}")
44
+ expect(subscription).to have_stream_from("activity_notification_channel_User##{test_target.id}")
45
+ end
46
+
47
+ it_behaves_like :notification_channel
48
+ end
49
+ end
50
+ end