activity_notification 1.7.1 → 2.0.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 (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