activity_notification 2.0.0 → 2.1.4

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 (202) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +22 -0
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +17 -0
  4. data/.github/pull_request_template.md +13 -0
  5. data/.gitignore +10 -3
  6. data/.travis.yml +6 -5
  7. data/CHANGELOG.md +60 -0
  8. data/Gemfile +8 -3
  9. data/Procfile +1 -1
  10. data/README.md +153 -1510
  11. data/activity_notification.gemspec +4 -1
  12. data/app/channels/activity_notification/notification_api_channel.rb +12 -0
  13. data/app/channels/activity_notification/notification_api_with_devise_channel.rb +46 -0
  14. data/app/channels/activity_notification/notification_channel.rb +2 -2
  15. data/app/channels/activity_notification/notification_with_devise_channel.rb +2 -2
  16. data/app/controllers/activity_notification/apidocs_controller.rb +75 -0
  17. data/app/controllers/activity_notification/notifications_api_controller.rb +143 -0
  18. data/app/controllers/activity_notification/notifications_api_with_devise_controller.rb +7 -0
  19. data/app/controllers/activity_notification/notifications_controller.rb +79 -53
  20. data/app/controllers/activity_notification/subscriptions_api_controller.rb +197 -0
  21. data/app/controllers/activity_notification/subscriptions_api_with_devise_controller.rb +7 -0
  22. data/app/controllers/activity_notification/subscriptions_controller.rb +78 -69
  23. data/app/views/activity_notification/notifications/default/_default.html.erb +18 -18
  24. data/app/views/activity_notification/notifications/default/_default_without_grouping.html.erb +14 -14
  25. data/app/views/activity_notification/notifications/default/index.html.erb +6 -6
  26. data/app/views/activity_notification/optional_targets/default/action_cable_channel/_default.html.erb +176 -0
  27. data/app/views/activity_notification/subscriptions/default/_form.html.erb +1 -1
  28. data/app/views/activity_notification/subscriptions/default/_notification_keys.html.erb +3 -31
  29. data/app/views/activity_notification/subscriptions/default/_subscription.html.erb +7 -7
  30. data/app/views/activity_notification/subscriptions/default/index.html.erb +11 -7
  31. data/bin/deploy_on_heroku.sh +3 -1
  32. data/docs/CODE_OF_CONDUCT.md +76 -0
  33. data/docs/CONTRIBUTING.md +36 -0
  34. data/docs/Functions.md +1130 -0
  35. data/docs/Setup.md +801 -0
  36. data/docs/Testing.md +148 -0
  37. data/gemfiles/Gemfile.rails-4.2 +5 -1
  38. data/gemfiles/Gemfile.rails-5.0 +6 -1
  39. data/gemfiles/Gemfile.rails-5.1 +6 -1
  40. data/gemfiles/Gemfile.rails-5.2 +6 -1
  41. data/gemfiles/{Gemfile.rails-6.0.rc → Gemfile.rails-6.0} +6 -5
  42. data/lib/activity_notification.rb +13 -0
  43. data/lib/activity_notification/apis/notification_api.rb +37 -93
  44. data/lib/activity_notification/apis/subscription_api.rb +20 -8
  45. data/lib/activity_notification/apis/swagger.rb +6 -0
  46. data/lib/activity_notification/common.rb +4 -1
  47. data/lib/activity_notification/config.rb +41 -21
  48. data/lib/activity_notification/controllers/common_api_controller.rb +30 -0
  49. data/lib/activity_notification/controllers/common_controller.rb +45 -21
  50. data/lib/activity_notification/controllers/concerns/swagger/error_responses.rb +55 -0
  51. data/lib/activity_notification/controllers/concerns/swagger/notifications_api.rb +273 -0
  52. data/lib/activity_notification/controllers/concerns/swagger/notifications_parameters.rb +92 -0
  53. data/lib/activity_notification/controllers/concerns/swagger/subscriptions_api.rb +405 -0
  54. data/lib/activity_notification/controllers/concerns/swagger/subscriptions_parameters.rb +50 -0
  55. data/lib/activity_notification/controllers/devise_authentication_controller.rb +7 -6
  56. data/lib/activity_notification/gem_version.rb +14 -0
  57. data/lib/activity_notification/helpers/errors.rb +2 -0
  58. data/lib/activity_notification/helpers/view_helpers.rb +4 -0
  59. data/lib/activity_notification/mailers/helpers.rb +17 -10
  60. data/lib/activity_notification/models/concerns/notifiable.rb +31 -15
  61. data/lib/activity_notification/models/concerns/subscriber.rb +12 -1
  62. data/lib/activity_notification/models/concerns/swagger/error_schema.rb +36 -0
  63. data/lib/activity_notification/models/concerns/swagger/notification_schema.rb +209 -0
  64. data/lib/activity_notification/models/concerns/swagger/subscription_schema.rb +162 -0
  65. data/lib/activity_notification/models/concerns/target.rb +36 -10
  66. data/lib/activity_notification/models/notification.rb +1 -0
  67. data/lib/activity_notification/models/subscription.rb +1 -0
  68. data/lib/activity_notification/optional_targets/action_cable_api_channel.rb +69 -0
  69. data/lib/activity_notification/optional_targets/action_cable_channel.rb +68 -0
  70. data/lib/activity_notification/optional_targets/base.rb +7 -13
  71. data/lib/activity_notification/orm/active_record/notification.rb +17 -1
  72. data/lib/activity_notification/orm/active_record/subscription.rb +1 -1
  73. data/lib/activity_notification/orm/dynamoid.rb +38 -3
  74. data/lib/activity_notification/orm/dynamoid/extension.rb +79 -1
  75. data/lib/activity_notification/orm/dynamoid/notification.rb +49 -14
  76. data/lib/activity_notification/orm/dynamoid/subscription.rb +2 -2
  77. data/lib/activity_notification/orm/mongoid.rb +32 -3
  78. data/lib/activity_notification/orm/mongoid/notification.rb +24 -6
  79. data/lib/activity_notification/orm/mongoid/subscription.rb +1 -1
  80. data/lib/activity_notification/rails/routes.rb +132 -48
  81. data/lib/activity_notification/renderable.rb +13 -2
  82. data/lib/activity_notification/roles/acts_as_notifiable.rb +39 -20
  83. data/lib/activity_notification/version.rb +1 -1
  84. data/lib/generators/activity_notification/controllers_generator.rb +2 -1
  85. data/lib/generators/templates/activity_notification.rb +8 -0
  86. data/lib/generators/templates/controllers/notifications_api_controller.rb +31 -0
  87. data/lib/generators/templates/controllers/notifications_api_with_devise_controller.rb +31 -0
  88. data/lib/generators/templates/controllers/notifications_controller.rb +1 -37
  89. data/lib/generators/templates/controllers/notifications_with_devise_controller.rb +1 -45
  90. data/lib/generators/templates/controllers/subscriptions_api_controller.rb +61 -0
  91. data/lib/generators/templates/controllers/subscriptions_api_with_devise_controller.rb +61 -0
  92. data/lib/generators/templates/controllers/subscriptions_controller.rb +14 -37
  93. data/lib/generators/templates/controllers/subscriptions_with_devise_controller.rb +14 -45
  94. data/lib/generators/templates/models/README +8 -4
  95. data/lib/generators/templates/models/notification.rb +1 -1
  96. data/lib/generators/templates/models/subscription.rb +1 -1
  97. data/package.json +8 -0
  98. data/spec/channels/notification_api_channel_shared_examples.rb +59 -0
  99. data/spec/channels/notification_api_channel_spec.rb +51 -0
  100. data/spec/channels/notification_api_with_devise_channel_spec.rb +78 -0
  101. data/spec/concerns/apis/notification_api_spec.rb +38 -3
  102. data/spec/concerns/models/notifiable_spec.rb +82 -18
  103. data/spec/concerns/models/subscriber_spec.rb +13 -16
  104. data/spec/concerns/models/target_spec.rb +32 -0
  105. data/spec/concerns/renderable_spec.rb +2 -2
  106. data/spec/config_spec.rb +26 -15
  107. data/spec/controllers/controller_spec_utility.rb +136 -0
  108. data/spec/controllers/notifications_api_controller_shared_examples.rb +506 -0
  109. data/spec/controllers/notifications_api_controller_spec.rb +19 -0
  110. data/spec/controllers/notifications_api_with_devise_controller_spec.rb +60 -0
  111. data/spec/controllers/notifications_controller_shared_examples.rb +54 -79
  112. data/spec/controllers/notifications_controller_spec.rb +1 -2
  113. data/spec/controllers/notifications_with_devise_controller_spec.rb +3 -12
  114. data/spec/controllers/subscriptions_api_controller_shared_examples.rb +750 -0
  115. data/spec/controllers/subscriptions_api_controller_spec.rb +19 -0
  116. data/spec/controllers/subscriptions_api_with_devise_controller_spec.rb +60 -0
  117. data/spec/controllers/subscriptions_controller_shared_examples.rb +94 -121
  118. data/spec/controllers/subscriptions_controller_spec.rb +1 -2
  119. data/spec/controllers/subscriptions_with_devise_controller_spec.rb +3 -12
  120. data/spec/helpers/view_helpers_spec.rb +4 -11
  121. data/spec/mailers/mailer_spec.rb +41 -0
  122. data/spec/models/notification_spec.rb +17 -0
  123. data/spec/models/subscription_spec.rb +8 -13
  124. data/spec/optional_targets/action_cable_api_channel_spec.rb +37 -0
  125. data/spec/optional_targets/action_cable_channel_spec.rb +44 -0
  126. data/spec/optional_targets/amazon_sns_spec.rb +0 -2
  127. data/spec/optional_targets/slack_spec.rb +0 -2
  128. data/spec/rails_app/Rakefile +9 -0
  129. data/spec/rails_app/app/assets/config/manifest.js +3 -0
  130. data/spec/rails_app/app/assets/images/.keep +0 -0
  131. data/spec/rails_app/app/controllers/admins_controller.rb +21 -0
  132. data/spec/rails_app/app/controllers/application_controller.rb +1 -1
  133. data/spec/rails_app/app/controllers/articles_controller.rb +6 -3
  134. data/spec/rails_app/app/controllers/spa_controller.rb +7 -0
  135. data/spec/rails_app/app/controllers/users/notifications_controller.rb +0 -65
  136. data/spec/rails_app/app/controllers/users/notifications_with_devise_controller.rb +0 -73
  137. data/spec/rails_app/app/controllers/users/subscriptions_controller.rb +0 -77
  138. data/spec/rails_app/app/controllers/users/subscriptions_with_devise_controller.rb +0 -85
  139. data/spec/rails_app/app/controllers/users_controller.rb +26 -0
  140. data/spec/rails_app/app/javascript/App.vue +40 -0
  141. data/spec/rails_app/app/javascript/components/DeviseTokenAuth.vue +82 -0
  142. data/spec/rails_app/app/javascript/components/Top.vue +98 -0
  143. data/spec/rails_app/app/javascript/components/notifications/Index.vue +200 -0
  144. data/spec/rails_app/app/javascript/components/notifications/Notification.vue +133 -0
  145. data/spec/rails_app/app/javascript/components/notifications/NotificationContent.vue +122 -0
  146. data/spec/rails_app/app/javascript/components/subscriptions/Index.vue +279 -0
  147. data/spec/rails_app/app/javascript/components/subscriptions/NewSubscription.vue +112 -0
  148. data/spec/rails_app/app/javascript/components/subscriptions/NotificationKey.vue +141 -0
  149. data/spec/rails_app/app/javascript/components/subscriptions/Subscription.vue +226 -0
  150. data/spec/rails_app/app/javascript/config/development.js +5 -0
  151. data/spec/rails_app/app/javascript/config/environment.js +7 -0
  152. data/spec/rails_app/app/javascript/config/production.js +5 -0
  153. data/spec/rails_app/app/javascript/config/test.js +5 -0
  154. data/spec/rails_app/app/javascript/packs/application.js +18 -0
  155. data/spec/rails_app/app/javascript/packs/spa.js +14 -0
  156. data/spec/rails_app/app/javascript/router/index.js +73 -0
  157. data/spec/rails_app/app/javascript/store/index.js +37 -0
  158. data/spec/rails_app/app/models/admin.rb +16 -15
  159. data/spec/rails_app/app/models/article.rb +26 -21
  160. data/spec/rails_app/app/models/comment.rb +24 -71
  161. data/spec/rails_app/app/models/dummy/dummy_group.rb +8 -0
  162. data/spec/rails_app/app/models/dummy/dummy_notifiable_target.rb +8 -0
  163. data/spec/rails_app/app/models/user.rb +44 -20
  164. data/spec/rails_app/app/views/activity_notification/notifications/default/article/_update.html.erb +146 -0
  165. data/spec/rails_app/app/views/articles/index.html.erb +51 -7
  166. data/spec/rails_app/app/views/articles/show.html.erb +1 -1
  167. data/spec/rails_app/app/views/layouts/_header.html.erb +8 -10
  168. data/spec/rails_app/app/views/spa/index.html.erb +2 -0
  169. data/spec/rails_app/babel.config.js +72 -0
  170. data/spec/rails_app/bin/webpack +18 -0
  171. data/spec/rails_app/bin/webpack-dev-server +18 -0
  172. data/spec/rails_app/config/application.rb +18 -2
  173. data/spec/rails_app/config/dynamoid.rb +11 -3
  174. data/spec/rails_app/config/environment.rb +2 -1
  175. data/spec/rails_app/config/environments/development.rb +5 -0
  176. data/spec/rails_app/config/environments/production.rb +6 -0
  177. data/spec/rails_app/config/environments/test.rb +5 -0
  178. data/spec/rails_app/config/initializers/activity_notification.rb +11 -3
  179. data/spec/rails_app/config/initializers/copy_it.aws.rb.template +6 -0
  180. data/spec/rails_app/config/initializers/devise_token_auth.rb +55 -0
  181. data/spec/rails_app/config/initializers/mysql.rb +9 -0
  182. data/spec/rails_app/config/locales/activity_notification.en.yml +2 -2
  183. data/spec/rails_app/config/routes.rb +37 -1
  184. data/spec/rails_app/config/webpack/development.js +5 -0
  185. data/spec/rails_app/config/webpack/environment.js +7 -0
  186. data/spec/rails_app/config/webpack/loaders/vue.js +6 -0
  187. data/spec/rails_app/config/webpack/production.js +5 -0
  188. data/spec/rails_app/config/webpack/test.js +5 -0
  189. data/spec/rails_app/config/webpacker.yml +97 -0
  190. data/spec/rails_app/db/migrate/20191201000000_add_tokens_to_users.rb +10 -0
  191. data/spec/rails_app/db/schema.rb +4 -1
  192. data/spec/rails_app/db/seeds.rb +10 -2
  193. data/spec/rails_app/lib/custom_optional_targets/raise_error.rb +14 -0
  194. data/spec/rails_app/package.json +23 -0
  195. data/spec/rails_app/postcss.config.js +12 -0
  196. data/spec/roles/acts_as_group_spec.rb +0 -2
  197. data/spec/roles/acts_as_notifiable_spec.rb +6 -8
  198. data/spec/roles/acts_as_notifier_spec.rb +0 -2
  199. data/spec/roles/acts_as_target_spec.rb +0 -4
  200. data/spec/spec_helper.rb +7 -15
  201. data/spec/version_spec.rb +31 -0
  202. metadata +191 -13
@@ -0,0 +1,148 @@
1
+ ## Testing
2
+
3
+ ### Testing your application
4
+
5
+ First, you need to configure ActivityNotification as described above.
6
+
7
+ #### Testing notifications with RSpec
8
+ Prepare target and notifiable model instances to test generating notifications (e.g. `@user` and `@comment`).
9
+ Then, you can call notify API and test if notifications of the target are generated.
10
+ ```ruby
11
+ # Prepare
12
+ @article_author = create(:user)
13
+ @comment = @article_author.articles.create.comments.create
14
+ expect(@article_author.notifications.unopened_only.count).to eq(0)
15
+
16
+ # Call notify API
17
+ @comment.notify :users
18
+
19
+ # Test generated notifications
20
+ expect(@article_author_user.notifications.unopened_only.count).to eq(1)
21
+ expect(@article_author_user.notifications.unopened_only.latest.notifiable).to eq(@comment)
22
+ ```
23
+
24
+ #### Testing email notifications with RSpec
25
+ Prepare target and notifiable model instances to test sending notification email.
26
+ Then, you can call notify API and test if notification email is sent.
27
+ ```ruby
28
+ # Prepare
29
+ @article_author = create(:user)
30
+ @comment = @article_author.articles.create.comments.create
31
+ expect(ActivityNotification::Mailer.deliveries.size).to eq(0)
32
+
33
+ # Call notify API and send email now
34
+ @comment.notify :users, send_later: false
35
+
36
+ # Test sent notification email
37
+ expect(ActivityNotification::Mailer.deliveries.size).to eq(1)
38
+ expect(ActivityNotification::Mailer.deliveries.first.to[0]).to eq(@article_author.email)
39
+ ```
40
+ Note that notification email will be sent asynchronously without false as *:send_later* option.
41
+ ```ruby
42
+ # Prepare
43
+ include ActiveJob::TestHelper
44
+ @article_author = create(:user)
45
+ @comment = @article_author.articles.create.comments.create
46
+ expect(ActivityNotification::Mailer.deliveries.size).to eq(0)
47
+
48
+ # Call notify API and send email asynchronously as default
49
+ # Test sent notification email with ActiveJob queue
50
+ expect {
51
+ perform_enqueued_jobs do
52
+ @comment.notify :users
53
+ end
54
+ }.to change { ActivityNotification::Mailer.deliveries.size }.by(1)
55
+ expect(ActivityNotification::Mailer.deliveries.first.to[0]).to eq(@article_author.email)
56
+ ```
57
+
58
+ ### Testing gem alone
59
+
60
+ #### Testing with RSpec
61
+ Pull git repository and execute RSpec.
62
+ ```console
63
+ $ git pull https://github.com/simukappu/activity_notification.git
64
+ $ cd activity_notification
65
+ $ bundle install —path vendor/bundle
66
+ $ bundle exec rspec
67
+ - or -
68
+ $ bundle exec rake
69
+ ```
70
+
71
+ ##### Testing with DynamoDB Local
72
+ You can use [DynamoDB Local](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.html) to test Amazon DynamoDB integration in your local environment.
73
+
74
+ At first, set up DynamoDB Local by install script:
75
+ ```console
76
+ $ bin/install_dynamodblocal.sh
77
+ ```
78
+ Then, start DynamoDB Local by start script:
79
+ ```console
80
+ $ bin/start_dynamodblocal.sh
81
+ ```
82
+ And you can stop DynamoDB Local by stop script:
83
+ ```console
84
+ $ bin/stop_dynamodblocal.sh
85
+ ```
86
+
87
+ In short, you can test DynamoDB integration by the following step:
88
+ ```console
89
+ $ git pull https://github.com/simukappu/activity_notification.git
90
+ $ cd activity_notification
91
+ $ bundle install —path vendor/bundle
92
+ $ bin/install_dynamodblocal.sh
93
+ $ bin/start_dynamodblocal.sh
94
+ $ AN_ORM=dynamoid bundle exec rspec
95
+ ```
96
+
97
+ #### Example Rails application
98
+ Test module includes example Rails application in *[spec/rails_app](/spec/rails_app)*. You can run the example application as common Rails application.
99
+ ```console
100
+ $ cd spec/rails_app
101
+ $ bin/rake db:migrate
102
+ $ bin/rake db:seed
103
+ $ bin/rails server
104
+ ```
105
+ Then, you can access <http://localhost:3000> for the example application.
106
+
107
+ ##### Run with your local database
108
+ As default, example Rails application runs with local SQLite database in *spec/rails_app/db/development.sqlite3*.
109
+ This application supports to run with your local MySQL, PostgreSQL, MongoDB.
110
+ Set **AN_TEST_DB** environment variable as follows.
111
+
112
+ To use MySQL:
113
+ ```console
114
+ $ export AN_TEST_DB=mysql
115
+ ```
116
+ To use PostgreSQL:
117
+ ```console
118
+ $ export AN_TEST_DB=postgresql
119
+ ```
120
+ To use MongoDB:
121
+ ```console
122
+ $ export AN_TEST_DB=mongodb
123
+ ```
124
+ When you set **mongodb** as *AN_TEST_DB*, you have to use *activity_notification* with MongoDB. Also set **AN_ORM** like:
125
+ ```console
126
+ $ export AN_ORM=mongoid
127
+ ```
128
+
129
+ You can also run this Rails application in cross database environment like these:
130
+
131
+ To use MySQL for your application and use MongoDB for *activity_notification*:
132
+ ```console
133
+ $ export AN_ORM=mongoid AN_TEST_DB=mysql
134
+ ```
135
+ To use PostgreSQL for your application and use Amazon DynamoDB for *activity_notification*:
136
+ ```console
137
+ $ export AN_ORM=dynamoid AN_TEST_DB=postgresql
138
+ ```
139
+
140
+ Then, configure *spec/rails_app/config/database.yml* or *spec/rails_app/config/mongoid.yml*, *spec/rails_app/config/dynamoid.rb* as your local database.
141
+ Finally, run database migration, seed data script and the example appliation.
142
+ ```console
143
+ $ cd spec/rails_app
144
+ $ # You don't need migration when you use MongoDB only (AN_ORM=mongoid and AN_TEST_DB=mongodb)
145
+ $ bin/rake db:migrate
146
+ $ bin/rake db:seed
147
+ $ bin/rails server Puma
148
+ ```
@@ -9,12 +9,16 @@ gem 'pg', '~> 0.21.0'
9
9
 
10
10
  group :development do
11
11
  gem 'bullet'
12
+ gem 'rack-cors'
12
13
  end
13
14
 
14
15
  group :test do
15
16
  gem 'ammeter'
16
17
  gem 'timecop'
17
- gem 'coveralls', require: false
18
+ gem 'committee'
19
+ gem 'committee-rails'
20
+ # gem 'coveralls', require: false
21
+ gem 'coveralls_reborn', require: false
18
22
  end
19
23
 
20
24
  gem 'dotenv-rails', groups: [:development, :test]
@@ -7,14 +7,19 @@ gem 'sqlite3', '~> 1.3.13'
7
7
 
8
8
  group :development do
9
9
  gem 'bullet'
10
+ gem 'rack-cors'
10
11
  end
11
12
 
12
13
  group :test do
14
+ gem 'rspec-rails', '< 4.0.0'
13
15
  gem 'rails-controller-testing'
14
16
  gem 'action-cable-testing'
15
17
  gem 'ammeter'
16
18
  gem 'timecop'
17
- gem 'coveralls', require: false
19
+ gem 'committee'
20
+ gem 'committee-rails'
21
+ # gem 'coveralls', require: false
22
+ gem 'coveralls_reborn', require: false
18
23
  end
19
24
 
20
25
  gem 'dotenv-rails', groups: [:development, :test]
@@ -6,14 +6,19 @@ gem 'rails', '~> 5.1.0'
6
6
 
7
7
  group :development do
8
8
  gem 'bullet'
9
+ gem 'rack-cors'
9
10
  end
10
11
 
11
12
  group :test do
13
+ gem 'rspec-rails', '< 4.0.0'
12
14
  gem 'rails-controller-testing'
13
15
  gem 'action-cable-testing'
14
16
  gem 'ammeter'
15
17
  gem 'timecop'
16
- gem 'coveralls', require: false
18
+ gem 'committee'
19
+ gem 'committee-rails'
20
+ # gem 'coveralls', require: false
21
+ gem 'coveralls_reborn', require: false
17
22
  end
18
23
 
19
24
  gem 'dotenv-rails', groups: [:development, :test]
@@ -6,14 +6,19 @@ gem 'rails', '~> 5.2.0'
6
6
 
7
7
  group :development do
8
8
  gem 'bullet'
9
+ gem 'rack-cors'
9
10
  end
10
11
 
11
12
  group :test do
13
+ gem 'rspec-rails', '< 4.0.0'
12
14
  gem 'rails-controller-testing'
13
15
  gem 'action-cable-testing'
14
16
  gem 'ammeter'
15
17
  gem 'timecop'
16
- gem 'coveralls', require: false
18
+ gem 'committee'
19
+ gem 'committee-rails'
20
+ # gem 'coveralls', require: false
21
+ gem 'coveralls_reborn', require: false
17
22
  end
18
23
 
19
24
  gem 'dotenv-rails', groups: [:development, :test]
@@ -2,20 +2,21 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec path: '../'
4
4
 
5
- gem 'rails', '~> 6.0.0.rc2'
5
+ gem 'rails', '~> 6.0.0'
6
6
 
7
7
  group :development do
8
8
  gem 'bullet'
9
+ gem 'rack-cors'
9
10
  end
10
11
 
11
12
  group :test do
12
- #TODO https://github.com/rails/rails/issues/35417
13
- gem 'rspec-rails', git: 'https://github.com/rspec/rspec-rails', branch: '4-0-dev'
14
-
15
13
  gem 'rails-controller-testing'
16
14
  gem 'ammeter'
17
15
  gem 'timecop'
18
- gem 'coveralls', require: false
16
+ gem 'committee'
17
+ gem 'committee-rails'
18
+ # gem 'coveralls', require: false
19
+ gem 'coveralls_reborn', require: false
19
20
  end
20
21
 
21
22
  gem 'dotenv-rails', groups: [:development, :test]
@@ -17,6 +17,7 @@ module ActivityNotification
17
17
  autoload :Config
18
18
  autoload :Renderable
19
19
  autoload :VERSION
20
+ autoload :GEM_VERSION
20
21
 
21
22
  module Mailers
22
23
  autoload :Helpers, 'activity_notification/mailers/helpers'
@@ -60,10 +61,22 @@ require 'activity_notification/helpers/errors'
60
61
  require 'activity_notification/helpers/polymorphic_helpers'
61
62
  require 'activity_notification/helpers/view_helpers'
62
63
  require 'activity_notification/controllers/common_controller'
64
+ require 'activity_notification/controllers/common_api_controller'
63
65
  require 'activity_notification/controllers/store_controller'
64
66
  require 'activity_notification/controllers/devise_authentication_controller'
65
67
  require 'activity_notification/optional_targets/base'
66
68
 
69
+ # Load Swagger API references
70
+ require 'activity_notification/apis/swagger'
71
+ require 'activity_notification/models/concerns/swagger/notification_schema'
72
+ require 'activity_notification/models/concerns/swagger/subscription_schema'
73
+ require 'activity_notification/models/concerns/swagger/error_schema'
74
+ require 'activity_notification/controllers/concerns/swagger/notifications_parameters'
75
+ require 'activity_notification/controllers/concerns/swagger/subscriptions_parameters'
76
+ require 'activity_notification/controllers/concerns/swagger/error_responses'
77
+ require 'activity_notification/controllers/concerns/swagger/notifications_api'
78
+ require 'activity_notification/controllers/concerns/swagger/subscriptions_api'
79
+
67
80
  # Load role for models
68
81
  require 'activity_notification/models'
69
82
 
@@ -10,10 +10,7 @@ module ActivityNotification
10
10
  # Defines mailer class to send notification
11
11
  set_notification_mailer
12
12
 
13
- # :only-rails5-plus#only-rails-with-callback-issue#except-dynamoid:
14
- # :only-rails5-plus#only-rails-without-callback-issue#except-dynamoid:
15
- # :except-rails5-plus#only-rails-with-callback-issue#except-dynamoid:
16
- # :except-rails5-plus#only-rails-without-callback-issue#except-dynamoid:
13
+ # :nocov:
17
14
  unless ActivityNotification.config.orm == :dynamoid
18
15
  # Selects all notification index.
19
16
  # ActivityNotification::Notification.all_index!
@@ -108,6 +105,8 @@ module ActivityNotification
108
105
  # @option options [String] :filtered_by_group_type (nil) Group type for filter, valid with :filtered_by_group_id
109
106
  # @option options [String] :filtered_by_group_id (nil) Group instance id for filter, valid with :filtered_by_group_type
110
107
  # @option options [String] :filtered_by_key (nil) Key of the notification for filter
108
+ # @option options [String] :later_than (nil) ISO 8601 format time to filter notification index later than specified time
109
+ # @option options [String] :earlier_than (nil) ISO 8601 format time to filter notification index earlier than specified time
111
110
  # @option options [Array|Hash] :custom_filter (nil) Custom notification filter (e.g. ["created_at >= ?", time.hour.ago] with ActiveRecord or {:created_at.gt => time.hour.ago} with Mongoid)
112
111
  # @return [ActiveRecord_AssociationRelation<Notificaion>, Mongoid::Criteria<Notificaion>] Database query of filtered notifications
113
112
  scope :filtered_by_options, ->(options = {}) {
@@ -126,6 +125,12 @@ module ActivityNotification
126
125
  if options.has_key?(:filtered_by_key)
127
126
  filtered_notifications = filtered_notifications.filtered_by_key(options[:filtered_by_key])
128
127
  end
128
+ if options.has_key?(:later_than)
129
+ filtered_notifications = filtered_notifications.later_than(Time.iso8601(options[:later_than]))
130
+ end
131
+ if options.has_key?(:earlier_than)
132
+ filtered_notifications = filtered_notifications.earlier_than(Time.iso8601(options[:earlier_than]))
133
+ end
129
134
  if options.has_key?(:custom_filter)
130
135
  filtered_notifications = filtered_notifications.where(options[:custom_filter])
131
136
  end
@@ -187,10 +192,7 @@ module ActivityNotification
187
192
  pluck(:key).uniq
188
193
  end
189
194
  end
190
- # :only-rails5-plus#only-rails-with-callback-issue#except-dynamoid:
191
- # :only-rails5-plus#only-rails-without-callback-issue#except-dynamoid:
192
- # :except-rails5-plus#only-rails-with-callback-issue#except-dynamoid:
193
- # :except-rails5-plus#only-rails-without-callback-issue#except-dynamoid:
195
+ # :nocov:
194
196
  end
195
197
 
196
198
  class_methods do
@@ -217,8 +219,6 @@ module ActivityNotification
217
219
  # @option options [Boolean] :notify_later (false) Whether it generates notifications asynchronously
218
220
  # @option options [Boolean] :send_email (true) Whether it sends notification email
219
221
  # @option options [Boolean] :send_later (true) Whether it sends notification email asynchronously
220
- # @option options [Boolean] :broadcast_action_cable (true) Whether it broadcasts notification to ActionCable channel
221
- # @option options [Hash] :action_cable_rendering ({fallback: :default}) Options for rendering params used by ActionCable, e.g. {fallback: :text} or {fallback: :default} etc. See also Renderable#render.
222
222
  # @option options [Boolean] :publish_optional_targets (true) Whether it publishes notification to optional targets
223
223
  # @option options [Boolean] :pass_full_options (false) Whether it passes full options to notifiable.notification_targets, not a key only
224
224
  # @option options [Hash<String, Hash>] :optional_targets ({}) Options for optional targets, keys are optional target name (:amazon_sns or :slack etc) and values are options
@@ -257,8 +257,6 @@ module ActivityNotification
257
257
  # @option options [Hash] :parameters ({}) Additional parameters of the notifications
258
258
  # @option options [Boolean] :send_email (true) Whether it sends notification email
259
259
  # @option options [Boolean] :send_later (true) Whether it sends notification email asynchronously
260
- # @option options [Boolean] :broadcast_action_cable (true) Whether it broadcasts notification to ActionCable channel
261
- # @option options [Hash] :action_cable_rendering ({fallback: :default}) Options for rendering params used by ActionCable, e.g. {fallback: :text} or {fallback: :default} etc. See also Renderable#render.
262
260
  # @option options [Boolean] :publish_optional_targets (true) Whether it publishes notification to optional targets
263
261
  # @option options [Boolean] :pass_full_options (false) Whether it passes full options to notifiable.notification_targets, not a key only
264
262
  # @option options [Hash<String, Hash>] :optional_targets ({}) Options for optional targets, keys are optional target name (:amazon_sns or :slack etc) and values are options
@@ -285,8 +283,6 @@ module ActivityNotification
285
283
  # @option options [Boolean] :notify_later (false) Whether it generates notifications asynchronously
286
284
  # @option options [Boolean] :send_email (true) Whether it sends notification email
287
285
  # @option options [Boolean] :send_later (true) Whether it sends notification email asynchronously
288
- # @option options [Boolean] :broadcast_action_cable (true) Whether it broadcasts notification to ActionCable channel
289
- # @option options [Hash] :action_cable_rendering ({fallback: :default}) Options for rendering params used by ActionCable, e.g. {fallback: :text} or {fallback: :default} etc. See also Renderable#render.
290
286
  # @option options [Boolean] :publish_optional_targets (true) Whether it publishes notification to optional targets
291
287
  # @option options [Hash<String, Hash>] :optional_targets ({}) Options for optional targets, keys are optional target name (:amazon_sns or :slack etc) and values are options
292
288
  # @return [Array<Notificaion>] Array of generated notifications
@@ -314,8 +310,6 @@ module ActivityNotification
314
310
  # @option options [Hash] :parameters ({}) Additional parameters of the notifications
315
311
  # @option options [Boolean] :send_email (true) Whether it sends notification email
316
312
  # @option options [Boolean] :send_later (true) Whether it sends notification email asynchronously
317
- # @option options [Boolean] :broadcast_action_cable (true) Whether it broadcasts notification to ActionCable channel
318
- # @option options [Hash] :action_cable_rendering ({fallback: :default}) Options for rendering params used by ActionCable, e.g. {fallback: :text} or {fallback: :default} etc. See also Renderable#render.
319
313
  # @option options [Boolean] :publish_optional_targets (true) Whether it publishes notification to optional targets
320
314
  # @option options [Hash<String, Hash>] :optional_targets ({}) Options for optional targets, keys are optional target name (:amazon_sns or :slack etc) and values are options
321
315
  # @return [Array<Notificaion>] Array of generated notifications
@@ -340,8 +334,6 @@ module ActivityNotification
340
334
  # @option options [Boolean] :notify_later (false) Whether it generates notifications asynchronously
341
335
  # @option options [Boolean] :send_email (true) Whether it sends notification email
342
336
  # @option options [Boolean] :send_later (true) Whether it sends notification email asynchronously
343
- # @option options [Boolean] :broadcast_action_cable (true) Whether it broadcasts notification to ActionCable channel
344
- # @option options [Hash] :action_cable_rendering ({fallback: :default}) Options for rendering params used by ActionCable, e.g. {fallback: :text} or {fallback: :default} etc. See also Renderable#render.
345
337
  # @option options [Boolean] :publish_optional_targets (true) Whether it publishes notification to optional targets
346
338
  # @option options [Hash<String, Hash>] :optional_targets ({}) Options for optional targets, keys are optional target name (:amazon_sns or :slack etc) and values are options
347
339
  # @return [Notification] Generated notification instance
@@ -351,7 +343,6 @@ module ActivityNotification
351
343
  else
352
344
  send_email = options.has_key?(:send_email) ? options[:send_email] : true
353
345
  send_later = options.has_key?(:send_later) ? options[:send_later] : true
354
- broadcast_action_cable = options.has_key?(:broadcast_action_cable) ? options[:broadcast_action_cable] : true
355
346
  publish_optional_targets = options.has_key?(:publish_optional_targets) ? options[:publish_optional_targets] : true
356
347
  # Generate notification
357
348
  notification = generate_notification(target, notifiable, options)
@@ -359,12 +350,6 @@ module ActivityNotification
359
350
  if notification.present? && send_email
360
351
  notification.send_notification_email({ send_later: send_later })
361
352
  end
362
- # Broadcast to ActionCable subscribers
363
- if notification.present? && broadcast_action_cable
364
- action_cable_rendering_options = options[:action_cable_rendering] || {}
365
- action_cable_rendering_options[:fallback] = action_cable_rendering_options[:fallback] || :default
366
- notification.broadcast_to_action_cable_channel(action_cable_rendering_options)
367
- end
368
353
  # Publish to optional targets
369
354
  if notification.present? && publish_optional_targets
370
355
  notification.publish_to_optional_targets(options[:optional_targets] || {})
@@ -390,8 +375,6 @@ module ActivityNotification
390
375
  # @option options [Hash] :parameters ({}) Additional parameters of the notifications
391
376
  # @option options [Boolean] :send_email (true) Whether it sends notification email
392
377
  # @option options [Boolean] :send_later (true) Whether it sends notification email asynchronously
393
- # @option options [Boolean] :broadcast_action_cable (true) Whether it broadcast∂s notification to ActionCable channel
394
- # @option options [Hash] :action_cable_rendering ({fallback: :default}) Options for rendering params used by ActionCable, e.g. {fallback: :text} or {fallback: :default} etc. See also Renderable#render.
395
378
  # @option options [Boolean] :publish_optional_targets (true) Whether it publishes notification to optional targets
396
379
  # @option options [Hash<String, Hash>] :optional_targets ({}) Options for optional targets, keys are optional target name (:amazon_sns or :slack etc) and values are options
397
380
  # @return [Notification] Generated notification instance
@@ -426,14 +409,15 @@ module ActivityNotification
426
409
  # @option options [String] :filtered_by_group_type (nil) Group type for filter, valid with :filtered_by_group_id
427
410
  # @option options [String] :filtered_by_group_id (nil) Group instance id for filter, valid with :filtered_by_group_type
428
411
  # @option options [String] :filtered_by_key (nil) Key of the notification for filter
429
- # @return [Integer] Number of opened notification records
430
- # @todo Add filter option
412
+ # @option options [String] :later_than (nil) ISO 8601 format time to filter notification index later than specified time
413
+ # @option options [String] :earlier_than (nil) ISO 8601 format time to filter notification index earlier than specified time
414
+ # @return [Array<Notification>] Opened notification records
431
415
  def open_all_of(target, options = {})
432
416
  opened_at = options[:opened_at] || Time.current
433
417
  target_unopened_notifications = target.notifications.unopened_only.filtered_by_options(options)
434
- unopened_notification_count = target_unopened_notifications.count
418
+ opened_notifications = target_unopened_notifications.to_a.map { |n| n.opened_at = opened_at; n }
435
419
  target_unopened_notifications.update_all(opened_at: opened_at)
436
- unopened_notification_count
420
+ opened_notifications
437
421
  end
438
422
 
439
423
  # Returns if group member of the notifications exists.
@@ -470,7 +454,7 @@ module ActivityNotification
470
454
  #
471
455
  # @return [Array<Notificaion>] Available options for kinds of notify methods
472
456
  def available_options
473
- [:key, :group, :group_expiry_delay, :notifier, :parameters, :send_email, :send_later].freeze
457
+ [:key, :group, :group_expiry_delay, :notifier, :parameters, :send_email, :send_later, :pass_full_options].freeze
474
458
  end
475
459
 
476
460
  # Defines mailer class to send notification
@@ -511,16 +495,23 @@ module ActivityNotification
511
495
 
512
496
  notification = new({ target: target, notifiable: notifiable, key: key, group: group, parameters: parameters, notifier: notifier, group_owner: group_owner })
513
497
  notification.prepare_to_store.save
498
+ notification.after_store
514
499
  notification
515
500
  end
516
501
  end
517
502
 
503
+ # :nocov:
518
504
  # Returns prepared notification object to store
519
505
  # @return [Object] prepared notification object to store
520
506
  def prepare_to_store
521
507
  self
522
508
  end
523
509
 
510
+ # Call after store action with stored notification
511
+ def after_store
512
+ end
513
+ # :nocov:
514
+
524
515
  # Sends notification email to the target.
525
516
  #
526
517
  # @param [Hash] options Options for notification email
@@ -538,64 +529,6 @@ module ActivityNotification
538
529
  end
539
530
  end
540
531
 
541
- # :only-rails5-plus#only-rails-with-callback-issue:
542
- # :only-rails5-plus#only-rails-without-callback-issue:
543
- # :only-rails5-plus#only-rails-with-callback-issue#except-dynamoid:
544
- # :only-rails5-plus#only-rails-without-callback-issue#except-dynamoid:
545
- if Rails::VERSION::MAJOR >= 5
546
- # Broadcast to ActionCable subscribers
547
- # @param [Hash] params Parameters for rendering notifications
548
- # @option params [String, Symbol] :target (nil) Target type name to find template or i18n text
549
- # @option params [String] :partial_root ("activity_notification/notifications/#{target}", controller.target_view_path, 'activity_notification/notifications/default') Partial template name
550
- # @option params [String] :partial (self.key.tr('.', '/')) Root path of partial template
551
- # @option params [String] :layout (nil) Layout template name
552
- # @option params [String] :layout_root ('layouts') Root path of layout template
553
- # @option params [String, Symbol] :fallback (nil) Fallback template to use when MissingTemplate is raised. Set :text to use i18n text as fallback.
554
- # @option params [String] :filter (nil) Filter option to load notification index (Nothing as auto, 'opened' or 'unopened')
555
- # @option params [String] :limit (nil) Limit to query for notifications
556
- # @option params [String] :without_grouping ('false') If notification index will include group members
557
- # @option params [String] :with_group_members ('false') If notification index will include group members
558
- # @option params [String] :filtered_by_type (nil) Notifiable type for filter
559
- # @option params [String] :filtered_by_group_type (nil) Group type for filter, valid with :filtered_by_group_id
560
- # @option params [String] :filtered_by_group_id (nil) Group instance id for filter, valid with :filtered_by_group_type
561
- # @option params [String] :filtered_by_key (nil) Key of the notification for filter
562
- # @option params [Hash] others Parameters to be set as locals
563
- def broadcast_to_action_cable_channel(params = {})
564
- if target.notification_action_cable_allowed?(notifiable, key) &&
565
- notifiable.notification_action_cable_allowed?(target, key)
566
- target_channel_name = "#{ActivityNotification.config.notification_channel_prefix}_#{target_type}#{ActivityNotification.config.composite_key_delimiter}#{target_id}"
567
- index_options = params.slice(:filter, :limit, :without_grouping, :with_group_members, :filtered_by_type, :filtered_by_group_type, :filtered_by_group_id, :filtered_by_key)
568
- ActionCable.server.broadcast(target_channel_name,
569
- id: id,
570
- view: render(ActivityNotification::NotificationsController.renderer, params),
571
- text: text(params),
572
- notifiable_path: notifiable_path,
573
- group_owner_id: group_owner_id,
574
- group_owner_view: group_owner? ? nil : group_owner.render(ActivityNotification::NotificationsController.renderer, params),
575
- unopened_notification_count: target.unopened_notification_count(index_options)
576
- )
577
- end
578
- end
579
- # :only-rails5-plus#only-rails-with-callback-issue:
580
- # :only-rails5-plus#only-rails-without-callback-issue:
581
- # :only-rails5-plus#only-rails-with-callback-issue#except-dynamoid:
582
- # :only-rails5-plus#only-rails-without-callback-issue#except-dynamoid:
583
- # :except-rails5-plus#only-rails-with-callback-issue:
584
- # :except-rails5-plus#only-rails-without-callback-issue:
585
- # :except-rails5-plus#only-rails-with-callback-issue#except-dynamoid:
586
- # :except-rails5-plus#only-rails-without-callback-issue#except-dynamoid:
587
- else
588
- # Broadcast to ActionCable subscribers
589
- # Do nothing with Rails < 5.0
590
- # @param [Hash] params Parameters for rendering notifications
591
- def broadcast_to_action_cable_channel(params = {})
592
- end
593
- end
594
- # :except-rails5-plus#only-rails-with-callback-issue:
595
- # :except-rails5-plus#only-rails-without-callback-issue:
596
- # :except-rails5-plus#only-rails-with-callback-issue#except-dynamoid:
597
- # :except-rails5-plus#only-rails-without-callback-issue#except-dynamoid:
598
-
599
532
  # Publishes notification to the optional targets.
600
533
  #
601
534
  # @param [Hash] options Options for optional targets
@@ -604,8 +537,13 @@ module ActivityNotification
604
537
  notifiable.optional_targets(target.to_resources_name, key).map { |optional_target|
605
538
  optional_target_name = optional_target.to_optional_target_name
606
539
  if optional_target_subscribed?(optional_target_name)
607
- optional_target.notify(self, options[optional_target_name] || {})
608
- [optional_target_name, true]
540
+ begin
541
+ optional_target.notify(self, options[optional_target_name] || {})
542
+ [optional_target_name, true]
543
+ rescue => e
544
+ Rails.logger.error(e)
545
+ [optional_target_name, e]
546
+ end
609
547
  else
610
548
  [optional_target_name, false]
611
549
  end
@@ -741,10 +679,16 @@ module ActivityNotification
741
679
  #
742
680
  # @return [String] Notifiable path URL to move after opening notification
743
681
  def notifiable_path
744
- notifiable.present? or raise ActiveRecord::RecordNotFound.new("Couldn't find notifiable #{notifiable_type}")
682
+ notifiable.blank? and raise ActivityNotification::NotifiableNotFoundError.new("Couldn't find associated notifiable (#{notifiable_type}) of #{self.class.name} with 'id'=#{id}")
745
683
  notifiable.notifiable_path(target_type, key)
746
684
  end
747
685
 
686
+ # Returns printable notifiable model name to show in view or email.
687
+ # @return [String] Printable notifiable model name
688
+ def printable_notifiable_name
689
+ notifiable.printable_notifiable_name(target, key)
690
+ end
691
+
748
692
  # Returns if the target subscribes this notification.
749
693
  # @return [Boolean] If the target subscribes the notification
750
694
  def subscribed?