activity_notification 2.3.2 → 2.4.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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build.yml +9 -36
  3. data/CHANGELOG.md +26 -1
  4. data/Gemfile +1 -1
  5. data/README.md +9 -1
  6. data/activity_notification.gemspec +5 -5
  7. data/ai-curated-specs/issues/172/design.md +220 -0
  8. data/ai-curated-specs/issues/172/tasks.md +326 -0
  9. data/ai-curated-specs/issues/188/design.md +227 -0
  10. data/ai-curated-specs/issues/188/requirements.md +78 -0
  11. data/ai-curated-specs/issues/188/tasks.md +203 -0
  12. data/ai-curated-specs/issues/188/upstream-contributions.md +592 -0
  13. data/ai-curated-specs/issues/50/design.md +235 -0
  14. data/ai-curated-specs/issues/50/requirements.md +49 -0
  15. data/ai-curated-specs/issues/50/tasks.md +232 -0
  16. data/app/controllers/activity_notification/notifications_api_controller.rb +22 -0
  17. data/app/controllers/activity_notification/notifications_controller.rb +27 -1
  18. data/app/mailers/activity_notification/mailer.rb +2 -2
  19. data/app/views/activity_notification/notifications/default/_index.html.erb +6 -1
  20. data/app/views/activity_notification/notifications/default/destroy_all.js.erb +6 -0
  21. data/docs/Setup.md +43 -6
  22. data/gemfiles/Gemfile.rails-7.0 +2 -0
  23. data/gemfiles/Gemfile.rails-7.2 +0 -2
  24. data/gemfiles/Gemfile.rails-8.0 +24 -0
  25. data/lib/activity_notification/apis/notification_api.rb +51 -2
  26. data/lib/activity_notification/controllers/concerns/swagger/notifications_api.rb +59 -0
  27. data/lib/activity_notification/helpers/view_helpers.rb +28 -0
  28. data/lib/activity_notification/mailers/helpers.rb +14 -7
  29. data/lib/activity_notification/models/concerns/target.rb +16 -0
  30. data/lib/activity_notification/models.rb +1 -1
  31. data/lib/activity_notification/notification_resilience.rb +115 -0
  32. data/lib/activity_notification/orm/dynamoid/extension.rb +4 -87
  33. data/lib/activity_notification/orm/dynamoid/notification.rb +19 -2
  34. data/lib/activity_notification/orm/dynamoid.rb +42 -6
  35. data/lib/activity_notification/rails/routes.rb +3 -2
  36. data/lib/activity_notification/version.rb +1 -1
  37. data/lib/activity_notification.rb +1 -0
  38. data/lib/generators/templates/controllers/notifications_api_controller.rb +5 -0
  39. data/lib/generators/templates/controllers/notifications_api_with_devise_controller.rb +5 -0
  40. data/lib/generators/templates/controllers/notifications_controller.rb +5 -0
  41. data/lib/generators/templates/controllers/notifications_with_devise_controller.rb +5 -0
  42. data/spec/concerns/apis/notification_api_spec.rb +161 -5
  43. data/spec/concerns/models/target_spec.rb +7 -0
  44. data/spec/controllers/controller_spec_utility.rb +1 -1
  45. data/spec/controllers/notifications_api_controller_shared_examples.rb +113 -0
  46. data/spec/controllers/notifications_controller_shared_examples.rb +150 -0
  47. data/spec/helpers/view_helpers_spec.rb +14 -0
  48. data/spec/jobs/notification_resilience_job_spec.rb +167 -0
  49. data/spec/mailers/notification_resilience_spec.rb +263 -0
  50. data/spec/models/notification_spec.rb +1 -1
  51. data/spec/models/subscription_spec.rb +1 -1
  52. data/spec/rails_app/app/helpers/devise_helper.rb +2 -0
  53. data/spec/rails_app/config/application.rb +1 -0
  54. data/spec/rails_app/config/initializers/zeitwerk.rb +10 -0
  55. metadata +67 -53
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3756e6a1dde16b628911625689f64a6514c7c43f42964453dcb04511f5cc6d5b
4
- data.tar.gz: 1964bd54d6a1521f8224bbc4dcc27fbefcf2bd9ca95090e45dfbbc2d2f38bba6
3
+ metadata.gz: 0f81f1308188c8ac3e07332a40b1fab62c5af3a43dbbe135a71303e31d403285
4
+ data.tar.gz: db55d9f9811dcceecd1f562feaf33949faf716ce6ab07e45f0f35b077b032923
5
5
  SHA512:
6
- metadata.gz: 92289fad6ce9f245663fa01b2335a486e3cde53c9e50ec2be2161fc1fefbe2953898530fa7a1c94522adc60f7e523ccea1bc1bce14808c9ae6bb2ca9cc750302
7
- data.tar.gz: dca9ddbd8d069b44848266a51346355fe382008b0deb61085903b334c39404935cff93a7a3118dd52ba9f89aa09e176f7beeba358ee4b4dd3fa5763dcd96c0d2
6
+ metadata.gz: b4287ae97e4d9f3f3788a5d0fc36b9eb9837880d1ed4289a2e881d32e8a61baecfcd9dc1f9f8e0846214a87fdd4a808e042a3ae77a283a2eb5d4d4bffa4f6411
7
+ data.tar.gz: 2be55085563ca99a32c029bcc5ecf5e3a025d42a72326ef0f40f218f123af478d2adf760bf5cb51a142a6e326d0bf6c33374c9116e2cd39f0d1b248d3e69b5bd
@@ -17,63 +17,36 @@ jobs:
17
17
  fail-fast: false
18
18
  matrix:
19
19
  gemfile:
20
- - gemfiles/Gemfile.rails-5.0
21
- - gemfiles/Gemfile.rails-5.1
22
- - gemfiles/Gemfile.rails-5.2
23
- - gemfiles/Gemfile.rails-6.0
24
- - gemfiles/Gemfile.rails-6.1
25
20
  - gemfiles/Gemfile.rails-7.0
26
21
  - gemfiles/Gemfile.rails-7.1
27
22
  - gemfiles/Gemfile.rails-7.2
23
+ - gemfiles/Gemfile.rails-8.0
28
24
  orm:
29
25
  - active_record
30
26
  - mongoid
31
27
  - dynamoid
32
28
  include:
33
29
  # https://www.ruby-lang.org/en/downloads
34
- - gemfile: gemfiles/Gemfile.rails-5.0
35
- ruby-version: 2.7.7
36
- - gemfile: gemfiles/Gemfile.rails-5.1
37
- ruby-version: 2.7.7
38
- - gemfile: gemfiles/Gemfile.rails-5.2
39
- ruby-version: 2.7.7
40
- - gemfile: gemfiles/Gemfile.rails-6.0
41
- ruby-version: 2.7.7
42
- - gemfile: gemfiles/Gemfile.rails-6.1
43
- ruby-version: 2.7.7
44
30
  - gemfile: gemfiles/Gemfile.rails-7.0
45
- ruby-version: 3.1.6
31
+ ruby-version: 3.2.9
46
32
  - gemfile: gemfiles/Gemfile.rails-7.1
47
- ruby-version: 3.2.4
33
+ ruby-version: 3.2.9
48
34
  - gemfile: gemfiles/Gemfile.rails-7.2
49
- ruby-version: 3.3.4
35
+ ruby-version: 3.3.9
36
+ - gemfile: gemfiles/Gemfile.rails-8.0
37
+ ruby-version: 3.4.5
50
38
  - gemfile: Gemfile
51
- ruby-version: 3.3.3
39
+ ruby-version: 3.4.5
52
40
  orm: active_record
53
41
  test-db: mysql
54
42
  - gemfile: Gemfile
55
- ruby-version: 3.3.3
43
+ ruby-version: 3.4.5
56
44
  orm: active_record
57
45
  test-db: postgresql
58
46
  - gemfile: Gemfile
59
- ruby-version: 3.3.3
47
+ ruby-version: 3.4.5
60
48
  orm: mongoid
61
49
  test-db: mongodb
62
- - gemfile: Gemfile
63
- ruby-version: head
64
- orm: active_record
65
- allow_failures: 'true'
66
- exclude:
67
- - gemfile: gemfiles/Gemfile.rails-6.0
68
- orm: dynamoid
69
- - gemfile: gemfiles/Gemfile.rails-6.1
70
- orm: dynamoid
71
- - gemfile: gemfiles/Gemfile.rails-7.0
72
- orm: dynamoid
73
- - gemfile: gemfiles/Gemfile.rails-7.1
74
- orm: dynamoid
75
- - gemfile: gemfiles/Gemfile.rails-7.2
76
- orm: dynamoid
77
50
 
78
51
  env:
79
52
  RAILS_ENV: test
data/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
+ ## 2.4.0 / 2025-08-20
2
+ [Full Changelog](http://github.com/simukappu/activity_notification/compare/v2.3.3...v2.4.0)
3
+
4
+ Enhancements:
5
+
6
+ * Support for Mongoid v9 - [#189](https://github.com/simukappu/activity_notification/issues/189)
7
+ * Support for Dynamoid v3.11.0+ (upgraded from v3.1.0) - [#188](https://github.com/simukappu/activity_notification/issues/188)
8
+ * Add bulk destroy notifications API - [#172](https://github.com/simukappu/activity_notification/issues/172)
9
+ * Add ids parameter to open_all notifications API - [#172](https://github.com/simukappu/activity_notification/issues/172)
10
+ * Add skip_validation option to open! method for notification handling - [#186](https://github.com/simukappu/activity_notification/issues/186) [#187](https://github.com/simukappu/activity_notification/pull/187)
11
+ * Add exception handling to Mailer jobs for missing notification - [#50](https://github.com/simukappu/activity_notification/issues/50)
12
+
13
+ Dependency:
14
+
15
+ * Remove support for Rails 5 and 6
16
+ * Update Mongoid dependency from development to runtime dependency - [#189](https://github.com/simukappu/activity_notification/issues/189)
17
+ * Update Dynamoid dependency from development to runtime dependency - [#188](https://github.com/simukappu/activity_notification/issues/188)
18
+
19
+ ## 2.3.3 / 2025-01-13
20
+ [Full Changelog](http://github.com/simukappu/activity_notification/compare/v2.3.2...v2.3.3)
21
+
22
+ Enhancements:
23
+
24
+ * Allow use with Rails 8.0 - [#182](https://github.com/simukappu/activity_notification/pull/182) [#183](https://github.com/simukappu/activity_notification/issues/183)
25
+
1
26
  ## 2.3.2 / 2024-09-23
2
- [Full Changelog](http://github.com/simukappu/activity_notification/compare/v2.3.0...v2.3.1)
27
+ [Full Changelog](http://github.com/simukappu/activity_notification/compare/v2.3.1...v2.3.2)
3
28
 
4
29
  Enhancements:
5
30
 
data/Gemfile CHANGED
@@ -2,7 +2,7 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'rails', '~> 7.1.0'
5
+ gem 'rails', '~> 8.0.0'
6
6
 
7
7
  group :production do
8
8
  gem 'sprockets-rails'
data/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  *activity_notification* provides integrated user activity notifications for [Ruby on Rails](https://rubyonrails.org). You can easily use it to configure multiple notification targets and make activity notifications with notifiable models, like adding comments, responding etc.
12
12
 
13
- *activity_notification* supports Rails 5.0+ with [ActiveRecord](https://guides.rubyonrails.org/active_record_basics.html), [Mongoid](https://mongoid.org) and [Dynamoid](https://github.com/Dynamoid/dynamoid) ORM. It is tested for [MySQL](https://www.mysql.com), [PostgreSQL](https://www.postgresql.org), [SQLite3](https://www.sqlite.org) with ActiveRecord, [MongoDB](https://www.mongodb.com) with Mongoid and [Amazon DynamoDB](https://aws.amazon.com/dynamodb) with Dynamoid. If you are using Rails 4.2, use [v2.1.4](https://rubygems.org/gems/activity_notification/versions/2.1.4) or older version of *activity_notification*.
13
+ *activity_notification* supports Rails 7.0+ with [ActiveRecord](https://guides.rubyonrails.org/active_record_basics.html), [Mongoid](https://mongoid.org) and [Dynamoid](https://github.com/Dynamoid/dynamoid) ORM. It is tested for [MySQL](https://www.mysql.com), [PostgreSQL](https://www.postgresql.org), [SQLite3](https://www.sqlite.org) with ActiveRecord, [MongoDB](https://www.mongodb.com) with Mongoid and [Amazon DynamoDB](https://aws.amazon.com/dynamodb) with Dynamoid v3.11.0+. If you are using Rails 5 or Rails 6, use [v2.3.3](https://rubygems.org/gems/activity_notification/versions/2.3.3) or older version of *activity_notification*.
14
14
 
15
15
 
16
16
  ## About
@@ -106,6 +106,8 @@ This sample application works with *activity_notification* REST API backend.
106
106
  - [Rendering notifications](/docs/Setup.md#rendering-notifications)
107
107
  - [Notification views](/docs/Setup.md#notification-views)
108
108
  - [i18n for notifications](/docs/Setup.md#i18n-for-notifications)
109
+ - [Managing notifications](/docs/Setup.md#managing-notifications)
110
+ - [Managing notifications](/docs/Setup.md#managing-notifications)
109
111
  - [Customizing controllers (optional)](/docs/Setup.md#customizing-controllers-optional)
110
112
  - [Functions](/docs/Functions.md#Functions)
111
113
  - [Email notification](/docs/Functions.md#email-notification)
@@ -284,6 +286,12 @@ See [Creating notifications](/docs/Setup.md#creating-notifications) for more det
284
286
 
285
287
  See [Displaying notifications](/docs/Setup.md#displaying-notifications) for more details.
286
288
 
289
+ ### Managing notifications
290
+
291
+ *activity_notification* provides APIs to manage notifications programmatically. You can mark notifications as opened (read), filter them, and perform bulk operations.
292
+
293
+ See [Managing notifications](/docs/Setup.md#managing-notifications) for more details.
294
+
287
295
  ### Run example Rails application
288
296
 
289
297
  Test module includes example Rails application in *[spec/rails_app](/spec/rails_app)*.
@@ -20,19 +20,19 @@ Gem::Specification.new do |s|
20
20
  s.require_paths = ["lib"]
21
21
  s.required_ruby_version = '>= 2.1.0'
22
22
 
23
- s.add_dependency 'railties', '>= 5.0.0', '< 7.3'
23
+ s.add_dependency 'railties', '>= 7.0.0', '< 8.1'
24
+ s.add_dependency 'mongoid', '>= 4.0.0', '< 10.0'
25
+ s.add_dependency 'dynamoid', '>= 3.11.0', '< 4.0'
24
26
  s.add_dependency 'i18n', '>= 0.5.0'
25
27
  s.add_dependency 'jquery-rails', '>= 3.1.1'
26
28
  s.add_dependency 'swagger-blocks', '>= 3.0.0'
27
29
 
28
30
  s.add_development_dependency 'puma', '>= 3.12.0'
29
- s.add_development_dependency 'sqlite3', '>= 1.3.13', '< 2.0'
31
+ s.add_development_dependency 'sqlite3', '>= 1.3.13'
30
32
  s.add_development_dependency 'mysql2', '>= 0.5.2'
31
33
  s.add_development_dependency 'pg', '>= 1.0.0'
32
- s.add_development_dependency 'mongoid', '>= 4.0.0', '< 9.0'
33
- s.add_development_dependency 'dynamoid', '3.1.0'
34
34
  s.add_development_dependency 'rspec-rails', '>= 3.8.0'
35
- s.add_development_dependency 'factory_bot_rails', '>= 4.11.0', '< 5.0.0'
35
+ s.add_development_dependency 'factory_bot_rails', '>= 4.11.0'
36
36
  s.add_development_dependency 'simplecov', '~> 0'
37
37
  s.add_development_dependency 'yard', '>= 0.9.16'
38
38
  s.add_development_dependency 'yard-activesupport-concern', '>= 0.0.1'
@@ -0,0 +1,220 @@
1
+ # Design Document: Bulk destroy notifications API
2
+
3
+ ## Issue Summary
4
+ GitHub Issue [#172](https://github.com/simukappu/activity_notification/issues/172) requests the ability to delete more than one notification for a target. Currently, only single notification deletion is available through the `destroy` API. The user wants a `bulk_destroy` API or provision to create custom APIs for bulk destroying notifications.
5
+
6
+ ## Current State Analysis
7
+
8
+ ### Existing Destroy Functionality
9
+ - **Single Destroy**: `DELETE /:target_type/:target_id/notifications/:id`
10
+ - Implemented in `NotificationsController#destroy`
11
+ - API version in `NotificationsApiController#destroy`
12
+ - Simply calls `@notification.destroy` on individual notification
13
+
14
+ ### Existing Bulk Operations Pattern
15
+ - **Bulk Open**: `POST /:target_type/:target_id/notifications/open_all`
16
+ - Implemented in `NotificationsController#open_all`
17
+ - Uses `@target.open_all_notifications(params)`
18
+ - Backend implementation in `NotificationApi#open_all_of`
19
+ - Uses `update_all(opened_at: opened_at)` for efficient bulk updates
20
+
21
+ ## Proposed Implementation
22
+
23
+ ### 1. Backend API Method (NotificationApi)
24
+ **File**: `lib/activity_notification/apis/notification_api.rb`
25
+
26
+ Add a new class method `destroy_all_of` following the pattern of `open_all_of`:
27
+
28
+ ```ruby
29
+ # Destroys all notifications of the target matching the filter criteria.
30
+ #
31
+ # @param [Object] target Target of the notifications to destroy
32
+ # @param [Hash] options Options for filtering notifications to destroy
33
+ # @option options [String] :filtered_by_type (nil) Notifiable type for filter
34
+ # @option options [Object] :filtered_by_group (nil) Group instance for filter
35
+ # @option options [String] :filtered_by_group_type (nil) Group type for filter, valid with :filtered_by_group_id
36
+ # @option options [String] :filtered_by_group_id (nil) Group instance id for filter, valid with :filtered_by_group_type
37
+ # @option options [String] :filtered_by_key (nil) Key of the notification for filter
38
+ # @option options [String] :later_than (nil) ISO 8601 format time to filter notifications later than specified time
39
+ # @option options [String] :earlier_than (nil) ISO 8601 format time to filter notifications earlier than specified time
40
+ # @option options [Array] :ids (nil) Array of specific notification IDs to destroy
41
+ # @return [Array<Notification>] Destroyed notification records
42
+ def destroy_all_of(target, options = {})
43
+ ```
44
+
45
+ ### 2. Target Model Method
46
+ **File**: `lib/activity_notification/models/concerns/target.rb`
47
+
48
+ Add instance method `destroy_all_notifications` following the pattern of `open_all_notifications`:
49
+
50
+ ```ruby
51
+ # Destroys all notifications of the target matching the filter criteria.
52
+ #
53
+ # @param [Hash] options Options for filtering notifications to destroy
54
+ # @option options [String] :filtered_by_type (nil) Notifiable type for filter
55
+ # @option options [Object] :filtered_by_group (nil) Group instance for filter
56
+ # @option options [String] :filtered_by_group_type (nil) Group type for filter, valid with :filtered_by_group_id
57
+ # @option options [String] :filtered_by_group_id (nil) Group instance id for filter, valid with :filtered_by_group_type
58
+ # @option options [String] :filtered_by_key (nil) Key of the notification for filter
59
+ # @option options [String] :later_than (nil) ISO 8601 format time to filter notifications later than specified time
60
+ # @option options [String] :earlier_than (nil) ISO 8601 format time to filter notifications earlier than specified time
61
+ # @option options [Array] :ids (nil) Array of specific notification IDs to destroy
62
+ # @return [Array<Notification>] Destroyed notification records
63
+ def destroy_all_notifications(options = {})
64
+ ```
65
+
66
+ ### 3. Controller Actions
67
+
68
+ #### Web Controller
69
+ **File**: `app/controllers/activity_notification/notifications_controller.rb`
70
+
71
+ Add new action `destroy_all`:
72
+
73
+ ```ruby
74
+ # Destroys all notifications of the target matching filter criteria.
75
+ #
76
+ # POST /:target_type/:target_id/notifications/destroy_all
77
+ # @overload destroy_all(params)
78
+ # @param [Hash] params Request parameters
79
+ # @option params [String] :filter (nil) Filter option to load notification index by their status (Nothing as auto, 'opened' or 'unopened')
80
+ # @option params [String] :limit (nil) Maximum number of notifications to return
81
+ # @option params [String] :without_grouping ('false') Whether notification index will include group members
82
+ # @option params [String] :with_group_members ('false') Whether notification index will include group members
83
+ # @option params [String] :filtered_by_type (nil) Notifiable type to filter notifications
84
+ # @option params [String] :filtered_by_group_type (nil) Group type to filter notifications, valid with :filtered_by_group_id
85
+ # @option params [String] :filtered_by_group_id (nil) Group instance ID to filter notifications, valid with :filtered_by_group_type
86
+ # @option params [String] :filtered_by_key (nil) Key of notifications to filter
87
+ # @option params [String] :later_than (nil) ISO 8601 format time to filter notifications later than specified time
88
+ # @option params [String] :earlier_than (nil) ISO 8601 format time to filter notifications earlier than specified time
89
+ # @option params [Array] :ids (nil) Array of specific notification IDs to destroy
90
+ # @option params [String] :reload ('true') Whether notification index will be reloaded
91
+ # @return [Response] JavaScript view for ajax request or redirects to back as default
92
+ def destroy_all
93
+ ```
94
+
95
+ #### API Controller
96
+ **File**: `app/controllers/activity_notification/notifications_api_controller.rb`
97
+
98
+ Add new action `destroy_all`:
99
+
100
+ ```ruby
101
+ # Destroys all notifications of the target matching filter criteria.
102
+ #
103
+ # POST /:target_type/:target_id/notifications/destroy_all
104
+ # @overload destroy_all(params)
105
+ # @param [Hash] params Request parameters
106
+ # @option params [String] :filtered_by_type (nil) Notifiable type to filter notifications
107
+ # @option params [String] :filtered_by_group_type (nil) Group type to filter notifications, valid with :filtered_by_group_id
108
+ # @option params [String] :filtered_by_group_id (nil) Group instance ID to filter notifications, valid with :filtered_by_group_type
109
+ # @option params [String] :filtered_by_key (nil) Key of notifications to filter
110
+ # @option params [String] :later_than (nil) ISO 8601 format time to filter notifications later than specified time
111
+ # @option params [String] :earlier_than (nil) ISO 8601 format time to filter notifications earlier than specified time
112
+ # @option params [Array] :ids (nil) Array of specific notification IDs to destroy
113
+ # @return [JSON] count: number of destroyed notification records, notifications: destroyed notifications
114
+ def destroy_all
115
+ ```
116
+
117
+ ### 4. Routes Configuration
118
+ **File**: Routes will be automatically generated by the existing `notify_to` helper
119
+
120
+ The route will be: `POST /:target_type/:target_id/notifications/destroy_all`
121
+
122
+ ### 5. View Templates
123
+ **Files**:
124
+ - `app/views/activity_notification/notifications/default/destroy_all.js.erb`
125
+ - Template generators will need to be updated to include the new view
126
+
127
+ ### 6. Swagger API Documentation
128
+ **File**: Update Swagger documentation to include the new bulk destroy endpoint
129
+
130
+ ### 7. Generator Templates
131
+ **Files**: Update controller generator templates to include the new `destroy_all` action:
132
+ - `lib/generators/templates/controllers/notifications_api_controller.rb`
133
+ - `lib/generators/templates/controllers/notifications_controller.rb`
134
+ - `lib/generators/templates/controllers/notifications_with_devise_controller.rb`
135
+
136
+ ## Implementation Details
137
+
138
+ ### Filter Options Support
139
+ The bulk destroy API will support the same filtering options as the existing `open_all` functionality:
140
+ - `filtered_by_type`: Filter by notifiable type
141
+ - `filtered_by_group_type` + `filtered_by_group_id`: Filter by group
142
+ - `filtered_by_key`: Filter by notification key
143
+ - `later_than` / `earlier_than`: Filter by time range
144
+ - `ids`: Array of specific notification IDs (new option for precise control)
145
+
146
+ ### Safety Considerations
147
+ 1. **Validation**: Ensure all notifications belong to the specified target
148
+ 2. **Permissions**: Leverage existing authentication/authorization patterns
149
+ 3. **Soft Delete**: Consider if soft delete should be supported (follow existing destroy pattern)
150
+ 4. **Callbacks**: Ensure any existing destroy callbacks are properly triggered
151
+
152
+ ### Performance Considerations
153
+ 1. **Batch Operations**: Use `destroy_all` for efficient database operations
154
+ 2. **Memory Usage**: For large datasets, consider pagination or streaming
155
+ 3. **Callbacks**: Balance between performance and callback execution
156
+
157
+ ### Error Handling
158
+ 1. **Partial Failures**: Handle cases where some notifications can't be destroyed
159
+ 2. **Validation Errors**: Provide meaningful error messages
160
+ 3. **Authorization Errors**: Consistent with existing error handling patterns
161
+
162
+ ## Testing Requirements
163
+
164
+ ### Unit Tests
165
+ - Test `NotificationApi#destroy_all_of` method
166
+ - Test `Target#destroy_all_notifications` method
167
+ - Test controller actions for both web and API versions
168
+
169
+ ### Integration Tests
170
+ - Test complete request/response cycle
171
+ - Test with various filter combinations
172
+ - Test error scenarios
173
+
174
+ ### Performance Tests
175
+ - Test with large datasets
176
+ - Verify efficient database queries
177
+
178
+ ## Migration Considerations
179
+ - No database schema changes required
180
+ - Backward compatible addition
181
+ - Follows existing patterns and conventions
182
+
183
+ ## Documentation Updates
184
+ - Update README.md with new bulk destroy functionality
185
+ - Update API documentation
186
+ - Update controller documentation
187
+ - Add examples to documentation
188
+
189
+ ## Alternative Implementation Options
190
+
191
+ ### Option 1: Single Endpoint with Multiple IDs
192
+ Instead of filter-based bulk destroy, accept an array of notification IDs:
193
+ ```
194
+ POST /:target_type/:target_id/notifications/destroy_all
195
+ Body: { "ids": [1, 2, 3, 4, 5] }
196
+ ```
197
+
198
+ ### Option 2: RESTful Bulk Operations
199
+ Follow RESTful conventions with a bulk operations endpoint:
200
+ ```
201
+ POST /:target_type/:target_id/notifications/bulk
202
+ Body: { "action": "destroy", "filters": {...} }
203
+ ```
204
+
205
+ ### Option 3: Query Parameter Approach
206
+ Use existing destroy endpoint with query parameters:
207
+ ```
208
+ DELETE /:target_type/:target_id/notifications?ids[]=1&ids[]=2&ids[]=3
209
+ ```
210
+
211
+ ## Recommended Approach
212
+ The proposed implementation follows the existing pattern established by `open_all` functionality, making it consistent with the current codebase architecture. This approach provides:
213
+
214
+ 1. **Consistency**: Matches existing bulk operation patterns
215
+ 2. **Flexibility**: Supports various filtering options
216
+ 3. **Safety**: Leverages existing validation and authorization
217
+ 4. **Performance**: Uses efficient bulk database operations
218
+ 5. **Maintainability**: Follows established code organization
219
+
220
+ The implementation should prioritize the filter-based approach (similar to `open_all`) while also supporting the `ids` parameter for precise control when needed.