activity_notification 2.0.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +22 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +17 -0
- data/.github/pull_request_template.md +13 -0
- data/.gitignore +10 -3
- data/.travis.yml +6 -5
- data/CHANGELOG.md +22 -0
- data/Gemfile +8 -2
- data/Procfile +1 -1
- data/README.md +153 -1510
- data/activity_notification.gemspec +4 -1
- data/app/channels/activity_notification/notification_api_channel.rb +12 -0
- data/app/channels/activity_notification/notification_api_with_devise_channel.rb +46 -0
- data/app/channels/activity_notification/notification_channel.rb +1 -1
- data/app/channels/activity_notification/notification_with_devise_channel.rb +1 -1
- data/app/controllers/activity_notification/apidocs_controller.rb +75 -0
- data/app/controllers/activity_notification/notifications_api_controller.rb +143 -0
- data/app/controllers/activity_notification/notifications_api_with_devise_controller.rb +7 -0
- data/app/controllers/activity_notification/notifications_controller.rb +79 -53
- data/app/controllers/activity_notification/subscriptions_api_controller.rb +197 -0
- data/app/controllers/activity_notification/subscriptions_api_with_devise_controller.rb +7 -0
- data/app/controllers/activity_notification/subscriptions_controller.rb +78 -69
- data/app/views/activity_notification/notifications/default/_default.html.erb +18 -18
- data/app/views/activity_notification/notifications/default/_default_without_grouping.html.erb +14 -14
- data/app/views/activity_notification/notifications/default/index.html.erb +6 -6
- data/app/views/activity_notification/optional_targets/default/action_cable_channel/_default.html.erb +176 -0
- data/app/views/activity_notification/subscriptions/default/_form.html.erb +1 -1
- data/app/views/activity_notification/subscriptions/default/_notification_keys.html.erb +3 -31
- data/app/views/activity_notification/subscriptions/default/_subscription.html.erb +7 -7
- data/app/views/activity_notification/subscriptions/default/index.html.erb +11 -7
- data/bin/deploy_on_heroku.sh +3 -1
- data/docs/CODE_OF_CONDUCT.md +76 -0
- data/docs/CONTRIBUTING.md +36 -0
- data/docs/Functions.md +1130 -0
- data/docs/Setup.md +674 -0
- data/docs/Testing.md +148 -0
- data/gemfiles/Gemfile.rails-4.2 +3 -0
- data/gemfiles/Gemfile.rails-5.0 +3 -0
- data/gemfiles/Gemfile.rails-5.1 +3 -0
- data/gemfiles/Gemfile.rails-5.2 +3 -0
- data/gemfiles/{Gemfile.rails-6.0.rc → Gemfile.rails-6.0} +5 -3
- data/lib/activity_notification.rb +13 -1
- data/lib/activity_notification/apis/notification_api.rb +29 -92
- data/lib/activity_notification/apis/subscription_api.rb +20 -8
- data/lib/activity_notification/apis/swagger.rb +6 -0
- data/lib/activity_notification/config.rb +41 -21
- data/lib/activity_notification/controllers/common_api_controller.rb +30 -0
- data/lib/activity_notification/controllers/common_controller.rb +44 -20
- data/lib/activity_notification/controllers/concerns/swagger/error_responses.rb +55 -0
- data/lib/activity_notification/controllers/concerns/swagger/notifications_api.rb +273 -0
- data/lib/activity_notification/controllers/concerns/swagger/notifications_parameters.rb +92 -0
- data/lib/activity_notification/controllers/concerns/swagger/subscriptions_api.rb +405 -0
- data/lib/activity_notification/controllers/concerns/swagger/subscriptions_parameters.rb +50 -0
- data/lib/activity_notification/controllers/devise_authentication_controller.rb +7 -6
- data/lib/activity_notification/gem_version.rb +14 -0
- data/lib/activity_notification/helpers/errors.rb +2 -0
- data/lib/activity_notification/helpers/view_helpers.rb +4 -0
- data/lib/activity_notification/mailers/helpers.rb +17 -10
- data/lib/activity_notification/models/concerns/notifiable.rb +26 -10
- data/lib/activity_notification/models/concerns/subscriber.rb +12 -1
- data/lib/activity_notification/models/concerns/swagger/error_schema.rb +36 -0
- data/lib/activity_notification/models/concerns/swagger/notification_schema.rb +209 -0
- data/lib/activity_notification/models/concerns/swagger/subscription_schema.rb +162 -0
- data/lib/activity_notification/models/concerns/target.rb +36 -10
- data/lib/activity_notification/models/notification.rb +1 -0
- data/lib/activity_notification/models/subscription.rb +1 -0
- data/lib/activity_notification/optional_targets/action_cable_api_channel.rb +69 -0
- data/lib/activity_notification/optional_targets/action_cable_channel.rb +68 -0
- data/lib/activity_notification/optional_targets/base.rb +7 -13
- data/lib/activity_notification/orm/active_record/notification.rb +17 -1
- data/lib/activity_notification/orm/active_record/subscription.rb +1 -1
- data/lib/activity_notification/orm/dynamoid.rb +28 -0
- data/lib/activity_notification/orm/dynamoid/extension.rb +79 -1
- data/lib/activity_notification/orm/dynamoid/notification.rb +1 -1
- data/lib/activity_notification/orm/dynamoid/subscription.rb +1 -1
- data/lib/activity_notification/orm/mongoid.rb +22 -0
- data/lib/activity_notification/orm/mongoid/notification.rb +17 -1
- data/lib/activity_notification/orm/mongoid/subscription.rb +1 -1
- data/lib/activity_notification/rails/routes.rb +132 -48
- data/lib/activity_notification/renderable.rb +13 -2
- data/lib/activity_notification/roles/acts_as_notifiable.rb +38 -20
- data/lib/activity_notification/version.rb +1 -1
- data/lib/generators/activity_notification/controllers_generator.rb +2 -1
- data/lib/generators/templates/activity_notification.rb +8 -0
- data/lib/generators/templates/controllers/notifications_api_controller.rb +31 -0
- data/lib/generators/templates/controllers/notifications_api_with_devise_controller.rb +31 -0
- data/lib/generators/templates/controllers/notifications_controller.rb +1 -37
- data/lib/generators/templates/controllers/notifications_with_devise_controller.rb +1 -45
- data/lib/generators/templates/controllers/subscriptions_api_controller.rb +61 -0
- data/lib/generators/templates/controllers/subscriptions_api_with_devise_controller.rb +61 -0
- data/lib/generators/templates/controllers/subscriptions_controller.rb +14 -37
- data/lib/generators/templates/controllers/subscriptions_with_devise_controller.rb +14 -45
- data/lib/generators/templates/models/README +8 -4
- data/lib/generators/templates/models/notification.rb +1 -1
- data/lib/generators/templates/models/subscription.rb +1 -1
- data/package.json +8 -0
- data/spec/channels/notification_api_channel_shared_examples.rb +59 -0
- data/spec/channels/notification_api_channel_spec.rb +51 -0
- data/spec/channels/notification_api_with_devise_channel_spec.rb +78 -0
- data/spec/concerns/apis/notification_api_spec.rb +37 -2
- data/spec/concerns/models/notifiable_spec.rb +64 -0
- data/spec/concerns/models/subscriber_spec.rb +13 -16
- data/spec/concerns/models/target_spec.rb +32 -0
- data/spec/concerns/renderable_spec.rb +2 -2
- data/spec/controllers/controller_spec_utility.rb +136 -0
- data/spec/controllers/notifications_api_controller_shared_examples.rb +506 -0
- data/spec/controllers/notifications_api_controller_spec.rb +19 -0
- data/spec/controllers/notifications_api_with_devise_controller_spec.rb +60 -0
- data/spec/controllers/notifications_controller_shared_examples.rb +54 -79
- data/spec/controllers/notifications_controller_spec.rb +1 -2
- data/spec/controllers/notifications_with_devise_controller_spec.rb +3 -12
- data/spec/controllers/subscriptions_api_controller_shared_examples.rb +750 -0
- data/spec/controllers/subscriptions_api_controller_spec.rb +19 -0
- data/spec/controllers/subscriptions_api_with_devise_controller_spec.rb +60 -0
- data/spec/controllers/subscriptions_controller_shared_examples.rb +94 -121
- data/spec/controllers/subscriptions_controller_spec.rb +1 -2
- data/spec/controllers/subscriptions_with_devise_controller_spec.rb +3 -12
- data/spec/helpers/view_helpers_spec.rb +4 -11
- data/spec/mailers/mailer_spec.rb +41 -0
- data/spec/models/notification_spec.rb +17 -0
- data/spec/models/subscription_spec.rb +0 -13
- data/spec/optional_targets/action_cable_api_channel_spec.rb +37 -0
- data/spec/optional_targets/action_cable_channel_spec.rb +44 -0
- data/spec/optional_targets/amazon_sns_spec.rb +0 -2
- data/spec/optional_targets/slack_spec.rb +0 -2
- data/spec/rails_app/Rakefile +9 -0
- data/spec/rails_app/app/assets/config/manifest.js +3 -0
- data/spec/rails_app/app/assets/images/.keep +0 -0
- data/spec/rails_app/app/controllers/admins_controller.rb +21 -0
- data/spec/rails_app/app/controllers/application_controller.rb +1 -1
- data/spec/rails_app/app/controllers/articles_controller.rb +6 -3
- data/spec/rails_app/app/controllers/spa_controller.rb +7 -0
- data/spec/rails_app/app/controllers/users/notifications_controller.rb +0 -65
- data/spec/rails_app/app/controllers/users/notifications_with_devise_controller.rb +0 -73
- data/spec/rails_app/app/controllers/users/subscriptions_controller.rb +0 -77
- data/spec/rails_app/app/controllers/users/subscriptions_with_devise_controller.rb +0 -85
- data/spec/rails_app/app/controllers/users_controller.rb +21 -0
- data/spec/rails_app/app/javascript/App.vue +104 -0
- data/spec/rails_app/app/javascript/components/DeviseTokenAuth.vue +83 -0
- data/spec/rails_app/app/javascript/components/Top.vue +99 -0
- data/spec/rails_app/app/javascript/components/notifications/Index.vue +200 -0
- data/spec/rails_app/app/javascript/components/notifications/Notification.vue +133 -0
- data/spec/rails_app/app/javascript/components/notifications/NotificationContent.vue +122 -0
- data/spec/rails_app/app/javascript/components/subscriptions/Index.vue +279 -0
- data/spec/rails_app/app/javascript/components/subscriptions/NewSubscription.vue +112 -0
- data/spec/rails_app/app/javascript/components/subscriptions/NotificationKey.vue +141 -0
- data/spec/rails_app/app/javascript/components/subscriptions/Subscription.vue +226 -0
- data/spec/rails_app/app/javascript/config/development.js +5 -0
- data/spec/rails_app/app/javascript/config/environment.js +7 -0
- data/spec/rails_app/app/javascript/config/production.js +5 -0
- data/spec/rails_app/app/javascript/config/test.js +5 -0
- data/spec/rails_app/app/javascript/packs/application.js +18 -0
- data/spec/rails_app/app/javascript/packs/spa.js +11 -0
- data/spec/rails_app/app/javascript/store/auth.js +37 -0
- data/spec/rails_app/app/models/admin.rb +16 -15
- data/spec/rails_app/app/models/article.rb +26 -21
- data/spec/rails_app/app/models/comment.rb +24 -71
- data/spec/rails_app/app/models/user.rb +43 -20
- data/spec/rails_app/app/views/activity_notification/notifications/default/article/_update.html.erb +146 -0
- data/spec/rails_app/app/views/articles/index.html.erb +51 -7
- data/spec/rails_app/app/views/articles/show.html.erb +1 -1
- data/spec/rails_app/app/views/layouts/_header.html.erb +8 -10
- data/spec/rails_app/app/views/spa/index.html.erb +2 -0
- data/spec/rails_app/babel.config.js +72 -0
- data/spec/rails_app/bin/webpack +18 -0
- data/spec/rails_app/bin/webpack-dev-server +18 -0
- data/spec/rails_app/config/application.rb +15 -2
- data/spec/rails_app/config/environment.rb +2 -1
- data/spec/rails_app/config/environments/development.rb +5 -0
- data/spec/rails_app/config/environments/production.rb +3 -0
- data/spec/rails_app/config/environments/test.rb +5 -0
- data/spec/rails_app/config/initializers/activity_notification.rb +8 -0
- data/spec/rails_app/config/initializers/devise_token_auth.rb +55 -0
- data/spec/rails_app/config/initializers/mysql.rb +9 -0
- data/spec/rails_app/config/locales/activity_notification.en.yml +2 -2
- data/spec/rails_app/config/routes.rb +33 -1
- data/spec/rails_app/config/webpack/development.js +5 -0
- data/spec/rails_app/config/webpack/environment.js +7 -0
- data/spec/rails_app/config/webpack/loaders/vue.js +6 -0
- data/spec/rails_app/config/webpack/production.js +5 -0
- data/spec/rails_app/config/webpack/test.js +5 -0
- data/spec/rails_app/config/webpacker.yml +97 -0
- data/spec/rails_app/db/migrate/20191201000000_add_tokens_to_users.rb +10 -0
- data/spec/rails_app/db/schema.rb +4 -1
- data/spec/rails_app/db/seeds.rb +1 -0
- data/spec/rails_app/lib/custom_optional_targets/raise_error.rb +14 -0
- data/spec/rails_app/package.json +23 -0
- data/spec/rails_app/postcss.config.js +12 -0
- data/spec/roles/acts_as_group_spec.rb +0 -2
- data/spec/roles/acts_as_notifiable_spec.rb +1 -3
- data/spec/roles/acts_as_notifier_spec.rb +0 -2
- data/spec/roles/acts_as_target_spec.rb +0 -4
- data/spec/spec_helper.rb +7 -15
- data/spec/version_spec.rb +31 -0
- metadata +187 -13
@@ -1,7 +1,11 @@
|
|
1
1
|
<div class="subscription_wrapper">
|
2
|
+
<div class="subscription_header">
|
3
|
+
<h1>Subscriptions for <%= @target.printable_target_name %></h1>
|
4
|
+
</div>
|
5
|
+
|
2
6
|
<% unless @subscriptions.nil? %>
|
3
7
|
<div class="subscription_header">
|
4
|
-
<
|
8
|
+
<h2>Configured subscriptions</h2>
|
5
9
|
</div>
|
6
10
|
<div class="subscriptions" id="subscriptions">
|
7
11
|
<%= render 'subscriptions', subscriptions: @subscriptions, option_params: @index_options %>
|
@@ -10,7 +14,7 @@
|
|
10
14
|
|
11
15
|
<% unless @notification_keys.nil? %>
|
12
16
|
<div class="subscription_header">
|
13
|
-
<
|
17
|
+
<h2>Unconfigured notification keys</h2>
|
14
18
|
</div>
|
15
19
|
<div class="notification_keys" id="notification_keys">
|
16
20
|
<%= render 'notification_keys', target: @target, notification_keys: @notification_keys, option_params: @index_options %>
|
@@ -18,7 +22,7 @@
|
|
18
22
|
<% end %>
|
19
23
|
|
20
24
|
<div class="subscription_header">
|
21
|
-
<
|
25
|
+
<h2>Create a new subscription</h2>
|
22
26
|
</div>
|
23
27
|
<div class="subscription_form" id="subscription_form">
|
24
28
|
<%= render 'form', target: @target, option_params: @index_options %>
|
@@ -26,6 +30,10 @@
|
|
26
30
|
</div>
|
27
31
|
|
28
32
|
<style>
|
33
|
+
.subscription_header h1 {
|
34
|
+
margin-bottom: 30px;
|
35
|
+
}
|
36
|
+
|
29
37
|
.fields_area {
|
30
38
|
border: 1px solid #e5e5e5;
|
31
39
|
width: 600px;
|
@@ -44,10 +52,6 @@
|
|
44
52
|
background-color: #f8f9fb;
|
45
53
|
}
|
46
54
|
|
47
|
-
.fields_area .fields_wrapper:last-child {
|
48
|
-
border-bottom: none;
|
49
|
-
}
|
50
|
-
|
51
55
|
.fields_area .fields_wrapper .fields_title_wrapper {
|
52
56
|
margin-bottom: 16px;
|
53
57
|
border-bottom: none;
|
data/bin/deploy_on_heroku.sh
CHANGED
@@ -6,9 +6,11 @@ CURRENT_BRANCH=`git symbolic-ref --short HEAD`
|
|
6
6
|
git checkout -b $HEROKU_DEPLOYMENT_BRANCH
|
7
7
|
bundle install
|
8
8
|
sed -i "" -e "s/^\/Gemfile.lock/# \/Gemfile.lock/g" .gitignore
|
9
|
+
cp spec/rails_app/bin/webpack* bin/
|
9
10
|
git add .gitignore
|
10
11
|
git add Gemfile.lock
|
11
|
-
git
|
12
|
+
git add bin/webpack*
|
13
|
+
git commit -m "Add Gemfile.lock and webpack"
|
12
14
|
git push heroku ${HEROKU_DEPLOYMENT_BRANCH}:master --force
|
13
15
|
git checkout $CURRENT_BRANCH
|
14
16
|
git branch -D $HEROKU_DEPLOYMENT_BRANCH
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
9
|
+
level of experience, education, socio-economic status, nationality, personal
|
10
|
+
appearance, race, religion, or sexual identity and orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
+
when an individual is representing the project or its community. Examples of
|
50
|
+
representing a project or community include using an official project e-mail
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
53
|
+
further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project team at shota.yamazaki.8@gmail.com. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
72
|
+
|
73
|
+
[homepage]: https://www.contributor-covenant.org
|
74
|
+
|
75
|
+
For answers to common questions about this code of conduct, see
|
76
|
+
https://www.contributor-covenant.org/faq
|
@@ -0,0 +1,36 @@
|
|
1
|
+
## How to contribute to *activity_notification*
|
2
|
+
|
3
|
+
#### **Did you find a bug?**
|
4
|
+
|
5
|
+
* **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/simukappu/activity_notification/issues).
|
6
|
+
|
7
|
+
* If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/simukappu/activity_notification/issues/new). Be sure to include a **title and clear description**, as much relevant information as possible.
|
8
|
+
|
9
|
+
#### **Did you write code set for a new feature or a patch that fixes a bug?**
|
10
|
+
|
11
|
+
* Open a new GitHub pull request with your code set.
|
12
|
+
|
13
|
+
* Ensure the pull request description clearly describes the problem and solution. Include the relevant issue number if applicable.
|
14
|
+
|
15
|
+
* Before submitting, please check the followings:
|
16
|
+
* Write tests with RSpec to cover your changes
|
17
|
+
* Write code documents as YARD format to cover your changes
|
18
|
+
* Write [README](/README.md) and [Functions](/docs/Functions.md) documents if applicable
|
19
|
+
|
20
|
+
#### **Did you fix whitespace, format code, or make a purely cosmetic patch?**
|
21
|
+
|
22
|
+
* Feel free to create a new GitHub pull request.
|
23
|
+
|
24
|
+
* If changes that are cosmetic in nature and do not add anything substantial to the stability, functionality, or testability of the gem may not be accepted.
|
25
|
+
|
26
|
+
#### **Do you intend to add a new feature or change an existing one?**
|
27
|
+
|
28
|
+
* Open an issue on GitHub to suggest your change and collect feedback about the change.
|
29
|
+
|
30
|
+
#### **Do you have questions about the source code?**
|
31
|
+
|
32
|
+
* If you're unable to find any answers from public information and your own investigation, you can ask any questions about how to use *activity_notification* by creating GitHub issue.
|
33
|
+
|
34
|
+
*activity_notification* is a volunteer effort. We appreciate any of your contribution!
|
35
|
+
|
36
|
+
Thank you!
|
data/docs/Functions.md
ADDED
@@ -0,0 +1,1130 @@
|
|
1
|
+
## Functions
|
2
|
+
|
3
|
+
### Email notification
|
4
|
+
|
5
|
+
*activity_notification* provides email notification to the notification targets.
|
6
|
+
|
7
|
+
#### Mailer setup
|
8
|
+
|
9
|
+
Set up SMTP server configuration for *ActionMailer*. Then, you need to set up the default URL options for the *activity_notification* mailer in each environment. Here is a possible configuration for *config/environments/development.rb*:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
|
13
|
+
```
|
14
|
+
|
15
|
+
Email notification is disabled as default. You can configure it to enable email notification in initializer *activity_notification.rb*.
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
config.email_enabled = true
|
19
|
+
```
|
20
|
+
|
21
|
+
You can also configure them for each model by *acts_as roles* like these:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
class User < ActiveRecord::Base
|
25
|
+
# Example using confirmed_at of devise field
|
26
|
+
# to decide whether activity_notification sends notification email to this user
|
27
|
+
acts_as_target email: :email, email_allowed: :confirmed_at
|
28
|
+
end
|
29
|
+
```
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
class Comment < ActiveRecord::Base
|
33
|
+
belongs_to :article
|
34
|
+
belongs_to :user
|
35
|
+
|
36
|
+
acts_as_notifiable :users,
|
37
|
+
targets: ->(comment, key) {
|
38
|
+
([comment.article.user] + comment.article.reload.commented_users.to_a - [comment.user]).uniq
|
39
|
+
},
|
40
|
+
# Allow notification email
|
41
|
+
email_allowed: true,
|
42
|
+
notifiable_path: :article_notifiable_path
|
43
|
+
|
44
|
+
def article_notifiable_path
|
45
|
+
article_path(article)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
#### Sender configuration
|
51
|
+
|
52
|
+
You can configure the notification *"from"* address inside of *activity_notification.rb* in two ways.
|
53
|
+
|
54
|
+
Using a simple email address as *String*:
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
config.mailer_sender = 'your_notification_sender@example.com'
|
58
|
+
```
|
59
|
+
|
60
|
+
Using a *Proc* to configure the sender based on the *notification.key*:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
config.mailer_sender = ->(key){ key == 'inquiry.post' ? 'support@example.com' : 'noreply@example.com' }
|
64
|
+
```
|
65
|
+
|
66
|
+
#### Email templates
|
67
|
+
|
68
|
+
*activity_notification* will look for email template in a similar way as notification views, but the view file name is not start with an underscore. For example, if you have a notification with *:key* set to *"notification.comment.reply"* and target_type *users*, the gem will look for a partial in *app/views/activity_notification/mailer/users/comment/reply.html.(|erb|haml|slim|something_else)*.
|
69
|
+
|
70
|
+
If this template is missing, the gem will look for a partial in *default* as the target type which means *activity_notification/mailer/default/_default.html.(|erb|haml|slim|something_else)*.
|
71
|
+
|
72
|
+
#### Email subject
|
73
|
+
|
74
|
+
*activity_notification* will use `"Notification of #{@notification.notifiable.printable_type.downcase}"` as default email subject. If it is defined, *activity_notification* will resolve email subject from *overriding_notification_email_subject* method in notifiable models. You can customize email subject like this:
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
class Comment < ActiveRecord::Base
|
78
|
+
belongs_to :article
|
79
|
+
belongs_to :user
|
80
|
+
|
81
|
+
acts_as_notifiable :users,
|
82
|
+
targets: ->(comment, key) {
|
83
|
+
([comment.article.user] + comment.article.reload.commented_users.to_a - [comment.user]).uniq
|
84
|
+
},
|
85
|
+
notifiable_path: :article_notifiable_path
|
86
|
+
|
87
|
+
def overriding_notification_email_subject(target, key)
|
88
|
+
if key == "comment.create"
|
89
|
+
"New comment to your article!"
|
90
|
+
else
|
91
|
+
"Notification for new comments!"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
```
|
97
|
+
|
98
|
+
If you use i18n for email, you can configure email subject in your locale files. See [i18n for email](#i18n-for-email).
|
99
|
+
|
100
|
+
#### Other header fields
|
101
|
+
|
102
|
+
Similarly to the [Email subject](#email-subject), the `From`, `Reply-To` and `Message-ID` headers are configurable per notifiable model. From and reply to will override the `config.mailer_sender` config setting.
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
class Comment < ActiveRecord::Base
|
106
|
+
belongs_to :article
|
107
|
+
belongs_to :user
|
108
|
+
|
109
|
+
acts_as_notifiable :users,
|
110
|
+
targets: ->(comment, key) {
|
111
|
+
([comment.article.user] + comment.article.commented_users.to_a - [comment.user]).uniq
|
112
|
+
},
|
113
|
+
notifiable_path: :article_notifiable_path
|
114
|
+
|
115
|
+
def overriding_notification_email_from(target, key)
|
116
|
+
"no-reply.article@example.com"
|
117
|
+
end
|
118
|
+
|
119
|
+
def overriding_notification_email_reply_to(target, key)
|
120
|
+
"no-reply.article+comment-#{self.id}@example.com"
|
121
|
+
end
|
122
|
+
|
123
|
+
def overriding_notification_email_message_id(target, key)
|
124
|
+
"https://www.example.com/article/#{article.id}@example.com/"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
```
|
128
|
+
|
129
|
+
#### i18n for email
|
130
|
+
|
131
|
+
The subject of notification email can be put in your locale *.yml* files as **mail_subject** field:
|
132
|
+
|
133
|
+
```yaml
|
134
|
+
notification:
|
135
|
+
user:
|
136
|
+
comment:
|
137
|
+
post:
|
138
|
+
text: "<p>Someone posted comments to your article</p>"
|
139
|
+
mail_subject: 'New comment to your article'
|
140
|
+
```
|
141
|
+
|
142
|
+
### Batch email notification
|
143
|
+
|
144
|
+
*activity_notification* provides batch email notification to the notification targets. You can send notification email daily, hourly or weekly and so on with a scheduler like *whenever*.
|
145
|
+
|
146
|
+
#### Batch mailer setup
|
147
|
+
|
148
|
+
Set up SMTP server configuration for *ActionMailer* and the default URL options for the *activity_notification* mailer in each environment.
|
149
|
+
|
150
|
+
Batch email notification is disabled as default. You can configure it to enable email notification in initializer *activity_notification.rb* like single email notification.
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
config.email_enabled = true
|
154
|
+
```
|
155
|
+
|
156
|
+
You can also configure them for each target model by *acts_as_target* role like this.
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
class User < ActiveRecord::Base
|
160
|
+
# Example using confirmed_at of devise field
|
161
|
+
# to decide whether activity_notification sends batch notification email to this user
|
162
|
+
acts_as_target email: :email, batch_email_allowed: :confirmed_at
|
163
|
+
end
|
164
|
+
```
|
165
|
+
|
166
|
+
Then, you can send batch notification email for unopened notifications only to the all specified targets with *batch_key*.
|
167
|
+
|
168
|
+
```ruby
|
169
|
+
# Send batch notification email to the users with unopened notifications
|
170
|
+
User.send_batch_unopened_notification_email(batch_key: 'batch.comment.post')
|
171
|
+
```
|
172
|
+
|
173
|
+
You can also add conditions to filter notifications, like this:
|
174
|
+
|
175
|
+
```ruby
|
176
|
+
# Send batch notification email to the users with unopened notifications of specified key in 1 hour
|
177
|
+
User.send_batch_unopened_notification_email(batch_key: 'batch.comment.post', filtered_by_key: 'comment.post', custom_filter: ["created_at >= ?", time.hour.ago])
|
178
|
+
```
|
179
|
+
|
180
|
+
#### Batch sender configuration
|
181
|
+
|
182
|
+
*activity_notification* uses same sender configuration of real-time email notification as batch email sender.
|
183
|
+
You can configure *config.mailer_sender* as simply *String* or *Proc* based on the *batch_key*:
|
184
|
+
|
185
|
+
```ruby
|
186
|
+
config.mailer_sender = ->(batch_key){ batch_key == 'batch.inquiry.post' ? 'support@example.com' : 'noreply@example.com' }
|
187
|
+
```
|
188
|
+
|
189
|
+
*batch_key* is specified by **:batch_key** option. If this option is not specified, the key of the first notification will be used as *batch_key*.
|
190
|
+
|
191
|
+
#### Batch email templates
|
192
|
+
|
193
|
+
*activity_notification* will look for batch email template in the same way as email notification using *batch_key*.
|
194
|
+
|
195
|
+
#### Batch email subject
|
196
|
+
|
197
|
+
*activity_notification* will resolve batch email subject as the same way as [email subject](#email-subject) with *batch_key*.
|
198
|
+
|
199
|
+
If you use i18n for batch email, you can configure batch email subject in your locale files. See [i18n for batch email](#i18n-for-batch-email).
|
200
|
+
|
201
|
+
#### i18n for batch email
|
202
|
+
|
203
|
+
The subject of batch notification email also can be put in your locale *.yml* files as **mail_subject** field for *batch_key*.
|
204
|
+
|
205
|
+
```yaml
|
206
|
+
notification:
|
207
|
+
user:
|
208
|
+
batch:
|
209
|
+
comment:
|
210
|
+
post:
|
211
|
+
mail_subject: 'New comments to your article'
|
212
|
+
```
|
213
|
+
|
214
|
+
### Grouping notifications
|
215
|
+
|
216
|
+
*activity_notification* provides the function for automatically grouping notifications. When you created a notification like this, all *unopened* notifications to the same target will be grouped by *article* set as **:group** options:
|
217
|
+
|
218
|
+
```ruby
|
219
|
+
@comment.notify :users key: 'comment.post', group: @comment.article
|
220
|
+
```
|
221
|
+
|
222
|
+
When you use default notification view, it is helpful to configure **acts_as_notification_group** (or *acts_as_group*) with *:printable_name* option to render group instance.
|
223
|
+
|
224
|
+
```ruby
|
225
|
+
class Article < ActiveRecord::Base
|
226
|
+
belongs_to :user
|
227
|
+
acts_as_notification_group printable_name: ->(article) { "article \"#{article.title}\"" }
|
228
|
+
end
|
229
|
+
```
|
230
|
+
|
231
|
+
You can use **group_owners_only** scope to filter owner notifications representing each group:
|
232
|
+
|
233
|
+
```ruby
|
234
|
+
# custom_notifications_controller.rb
|
235
|
+
def index
|
236
|
+
@notifications = @target.notifications.group_owners_only
|
237
|
+
end
|
238
|
+
```
|
239
|
+
*notification_index* and *notification_index_with_attributes* methods also use *group_owners_only* scope internally.
|
240
|
+
|
241
|
+
And you can render them in a view like this:
|
242
|
+
```erb
|
243
|
+
<% if notification.group_member_exists? %>
|
244
|
+
<%= "#{notification.notifier.name} and #{notification.group_member_count} other users" %>
|
245
|
+
<% else %>
|
246
|
+
<%= "#{notification.notifier.name}" %>
|
247
|
+
<% end %>
|
248
|
+
<%= "posted comments to your article \"#{notification.group.title}\"" %>
|
249
|
+
```
|
250
|
+
|
251
|
+
This presentation will be shown to target users as *Kevin and 7 other users posted comments to your article "Let's use Ruby"*.
|
252
|
+
|
253
|
+
You can also use `%{group_member_count}`, `%{group_notification_count}`, `%{group_member_notifier_count}` and `%{group_notifier_count}` in i18n text as a field:
|
254
|
+
|
255
|
+
```yaml
|
256
|
+
notification:
|
257
|
+
user:
|
258
|
+
comment:
|
259
|
+
post:
|
260
|
+
text: "<p>%{notifier_name} and %{group_member_notifier_count} other users posted %{group_notification_count} comments to your article</p>"
|
261
|
+
mail_subject: 'New comment to your article'
|
262
|
+
```
|
263
|
+
|
264
|
+
Then, you will see *"Kevin and 7 other users posted 10 comments to your article"*.
|
265
|
+
|
266
|
+
|
267
|
+
### Subscription management
|
268
|
+
|
269
|
+
*activity_notification* provides the function for subscription management of notifications and notification email.
|
270
|
+
|
271
|
+
#### Configuring subscriptions
|
272
|
+
|
273
|
+
Subscription management is disabled as default. You can configure it to enable subscription management in initializer *activity_notification.rb*.
|
274
|
+
|
275
|
+
```ruby
|
276
|
+
config.subscription_enabled = true
|
277
|
+
```
|
278
|
+
|
279
|
+
This makes all target model subscribers. You can also configure them for each target model by *acts_as_target* role like this:
|
280
|
+
|
281
|
+
```ruby
|
282
|
+
class User < ActiveRecord::Base
|
283
|
+
# Example using confirmed_at of devise field
|
284
|
+
# to decide whether activity_notification manages subscriptions of this user
|
285
|
+
acts_as_target email: :email, email_allowed: :confirmed_at, subscription_allowed: :confirmed_at
|
286
|
+
end
|
287
|
+
```
|
288
|
+
|
289
|
+
If you do not have a subscriptions table in you database, create a migration for subscriptions and migrate the database in your Rails project:
|
290
|
+
|
291
|
+
```console
|
292
|
+
$ bin/rails generate activity_notification:migration CreateSubscriptions -t subscriptions
|
293
|
+
$ bin/rake db:migrate
|
294
|
+
```
|
295
|
+
If you are using a different table name than the default "subscriptions", change the settings in your config/initializers/activity_notification.rb file, e.g, if you use the table name "notifications_subscription" instead:
|
296
|
+
|
297
|
+
```
|
298
|
+
config.subscription_table_name = "notifications_subscriptions"
|
299
|
+
```
|
300
|
+
|
301
|
+
#### Managing subscriptions
|
302
|
+
|
303
|
+
Subscriptions are managed by instances of **ActivityNotification::Subscription** model which belongs to *target* and *key* of the notification.
|
304
|
+
*Subscription#subscribing* manages subscription of notifications.
|
305
|
+
*true* means the target will receive the notifications with this key.
|
306
|
+
*false* means the target will not receive these notifications.
|
307
|
+
*Subscription#subscribing_to_email* manages subscription of notification email.
|
308
|
+
*true* means the target will receive the notification email with this key including batch notification email with this *batch_key*.
|
309
|
+
*false* means the target will not receive these notification email.
|
310
|
+
|
311
|
+
As default, all target subscribes to notification and notification email when subscription record does not exist in your database.
|
312
|
+
You can change this **subscribe_as_default** parameter in initializer *activity_notification.rb*.
|
313
|
+
|
314
|
+
```ruby
|
315
|
+
config.subscribe_as_default = false
|
316
|
+
```
|
317
|
+
|
318
|
+
Then, all target does not subscribe to notification and notification email and will not receive any notifications as default.
|
319
|
+
|
320
|
+
You can create subscription record from subscription API in your target model like this:
|
321
|
+
|
322
|
+
```ruby
|
323
|
+
# Subscribe 'comment.reply' notifications and notification email
|
324
|
+
user.create_subscription(key: 'comment.reply')
|
325
|
+
|
326
|
+
# Subscribe 'comment.reply' notifications but does not subscribe notification email
|
327
|
+
user.create_subscription(key: 'comment.reply', subscribing_to_email: false)
|
328
|
+
|
329
|
+
# Unsubscribe 'comment.reply' notifications and notification email
|
330
|
+
user.create_subscription(key: 'comment.reply', subscribing: false)
|
331
|
+
```
|
332
|
+
|
333
|
+
You can also update subscriptions like this:
|
334
|
+
|
335
|
+
```ruby
|
336
|
+
# Subscribe 'comment.reply' notifications and notification email
|
337
|
+
user.find_or_create_subscription('comment.reply').subscribe
|
338
|
+
|
339
|
+
# Unsubscribe 'comment.reply' notifications and notification email
|
340
|
+
user.find_or_create_subscription('comment.reply').unsubscribe
|
341
|
+
|
342
|
+
# Unsubscribe 'comment.reply' notification email
|
343
|
+
user.find_or_create_subscription('comment.reply').unsubscribe_to_email
|
344
|
+
```
|
345
|
+
|
346
|
+
#### Customizing subscriptions
|
347
|
+
|
348
|
+
*activity_notification* provides basic controllers and views to manage the subscriptions.
|
349
|
+
|
350
|
+
Add subscription routing to *config/routes.rb* for the target (e.g. *:users*):
|
351
|
+
|
352
|
+
```ruby
|
353
|
+
Rails.application.routes.draw do
|
354
|
+
subscribed_by :users
|
355
|
+
end
|
356
|
+
```
|
357
|
+
|
358
|
+
or, you can also configure it with notifications like this:
|
359
|
+
|
360
|
+
```ruby
|
361
|
+
Rails.application.routes.draw do
|
362
|
+
notify_to :users, with_subscription: true
|
363
|
+
end
|
364
|
+
```
|
365
|
+
|
366
|
+
Then, you can access *users/1/subscriptions* and use *[ActivityNotification::SubscriptionsController](/app/controllers/activity_notification/subscriptions_controller.rb)* or *[ActivityNotification::SubscriptionsWithDeviseController](/app/controllers/activity_notification/subscriptions_with_devise_controller.rb)* to manage the subscriptions.
|
367
|
+
|
368
|
+
You can see sample subscription management view in demo application here: *https://activity-notification-example.herokuapp.com/users/1/subscriptions*
|
369
|
+
|
370
|
+
If you would like to customize subscription controllers or views, you can use generators like notifications:
|
371
|
+
|
372
|
+
* Customize subscription controllers
|
373
|
+
|
374
|
+
1. Create your custom controllers using controller generator with a target:
|
375
|
+
|
376
|
+
```console
|
377
|
+
$ bin/rails generate activity_notification:controllers users -c subscriptions subscriptions_with_devise
|
378
|
+
```
|
379
|
+
|
380
|
+
2. Tell the router to use this controller:
|
381
|
+
|
382
|
+
```ruby
|
383
|
+
notify_to :users, with_subscription: { controller: 'users/subscriptions' }
|
384
|
+
```
|
385
|
+
|
386
|
+
* Customize subscription views
|
387
|
+
|
388
|
+
```console
|
389
|
+
$ bin/rails generate activity_notification:views users -v subscriptions
|
390
|
+
```
|
391
|
+
|
392
|
+
|
393
|
+
### REST API backend
|
394
|
+
|
395
|
+
*activity_notification* provides REST API backend to operate notifications and subscriptions.
|
396
|
+
|
397
|
+
#### Configuring REST API backend
|
398
|
+
|
399
|
+
You can configure *activity_notification* routes as REST API backend with **:api_mode** option of *notify_to* method. See [Routes as REST API backend](#routes-as-rest-api-backend) for more details. With *:api_mode* option, *activity_notification* uses *[ActivityNotification::NotificationsApiController](/app/controllers/activity_notification/notifications_api_controller.rb)* instead of *[ActivityNotification::NotificationsController](/app/controllers/activity_notification/notifications_controller.rb)*.
|
400
|
+
|
401
|
+
In addition, you can use *:with_subscription* option with *:api_mode* to enable subscription management like this:
|
402
|
+
|
403
|
+
```ruby
|
404
|
+
Rails.application.routes.draw do
|
405
|
+
scope :api do
|
406
|
+
scope :"v2" do
|
407
|
+
notify_to :users, api_mode: true, with_subscription: true
|
408
|
+
end
|
409
|
+
end
|
410
|
+
end
|
411
|
+
```
|
412
|
+
|
413
|
+
Then, *activity_notification* uses *[ActivityNotification::SubscriptionsApiController](/app/controllers/activity_notification/subscriptions_api_controller.rb)* instead of *[ActivityNotification::SubscriptionsController](/app/controllers/activity_notification/subscriptions_controller.rb)*, and you can call *activity_notification* REST API as */api/v2/notifications* and */api/v2/subscriptions* from your frontend application.
|
414
|
+
|
415
|
+
When you want to use REST API backend integrated with Devise authentication, see [REST API backend with Devise Token Auth](#rest-api-backend-with-devise-token-auth).
|
416
|
+
|
417
|
+
You can see [sample single page application](/spec/rails_app/app/javascript/) using [Vue.js](https://vuejs.org) as a part of example Rails application. This sample application works with *activity_notification* REST API backend.
|
418
|
+
|
419
|
+
#### API reference as OpenAPI Specification
|
420
|
+
|
421
|
+
*activity_notification* provides API reference as [OpenAPI Specification](https://github.com/OAI/OpenAPI-Specification).
|
422
|
+
|
423
|
+
OpenAPI Specification in [online demo](https://activity-notification-example.herokuapp.com/) is published here: **https://activity-notification-example.herokuapp.com/api/v2/apidocs**
|
424
|
+
|
425
|
+
Public API reference is also hosted in [SwaggerHub](https://swagger.io/tools/swaggerhub/) here: **https://app.swaggerhub.com/apis/simukappu/activity-notification/**
|
426
|
+
|
427
|
+
You can also publish OpenAPI Specification in your own application using *[ActivityNotification::ApidocsController](/app/controllers/activity_notification/apidocs_controller.rb)* like this:
|
428
|
+
|
429
|
+
```ruby
|
430
|
+
Rails.application.routes.draw do
|
431
|
+
scope :api do
|
432
|
+
scope :"v2" do
|
433
|
+
resources :apidocs, only: [:index], controller: 'activity_notification/apidocs'
|
434
|
+
end
|
435
|
+
end
|
436
|
+
end
|
437
|
+
```
|
438
|
+
|
439
|
+
You can use [Swagger UI](https://swagger.io/tools/swagger-ui/) with this OpenAPI Specification to visualize and interact with *activity_notification* API’s resources.
|
440
|
+
|
441
|
+
|
442
|
+
### Integration with Devise
|
443
|
+
|
444
|
+
*activity_notification* supports to integrate with devise authentication.
|
445
|
+
|
446
|
+
#### Configuring integration with Devise authentication
|
447
|
+
|
448
|
+
Add **:with_devise** option in notification routing to *config/routes.rb* for the target:
|
449
|
+
|
450
|
+
```ruby
|
451
|
+
Rails.application.routes.draw do
|
452
|
+
devise_for :users
|
453
|
+
# Integrated with Devise
|
454
|
+
notify_to :users, with_devise: :users
|
455
|
+
end
|
456
|
+
```
|
457
|
+
|
458
|
+
Then *activity_notification* will use *[ActivityNotification::NotificationsWithDeviseController](/app/controllers/activity_notification/notifications_with_devise_controller.rb)* as a notifications controller. The controller actions automatically call *authenticate_user!* and the user will be restricted to access and operate own notifications only, not others'.
|
459
|
+
|
460
|
+
*Hint*: HTTP 403 Forbidden will be returned for unauthorized notifications.
|
461
|
+
|
462
|
+
#### Using different model as target
|
463
|
+
|
464
|
+
You can also use different model from Devise resource as a target. When you will add this to *config/routes.rb*:
|
465
|
+
|
466
|
+
```ruby
|
467
|
+
Rails.application.routes.draw do
|
468
|
+
devise_for :users
|
469
|
+
# Integrated with Devise for different model
|
470
|
+
notify_to :admins, with_devise: :users
|
471
|
+
end
|
472
|
+
```
|
473
|
+
|
474
|
+
and add **:devise_resource** option to *acts_as_target* in the target model:
|
475
|
+
|
476
|
+
```ruby
|
477
|
+
class Admin < ActiveRecord::Base
|
478
|
+
belongs_to :user
|
479
|
+
acts_as_target devise_resource: :user
|
480
|
+
end
|
481
|
+
```
|
482
|
+
|
483
|
+
*activity_notification* will authenticate *:admins* notifications with devise authentication for *:users*.
|
484
|
+
In this example, *activity_notification* will confirm *admin* belonging to authenticated *user* by Devise.
|
485
|
+
|
486
|
+
#### Configuring simple default routes
|
487
|
+
|
488
|
+
You can configure simple default routes for authenticated users, like */notifications* instead of */users/1/notifications*. Use **:devise_default_routes** option like this:
|
489
|
+
|
490
|
+
```ruby
|
491
|
+
Rails.application.routes.draw do
|
492
|
+
devise_for :users
|
493
|
+
notify_to :users, with_devise: :users, devise_default_routes: true
|
494
|
+
end
|
495
|
+
```
|
496
|
+
|
497
|
+
If you use multiple notification targets with Devise, you can also use this option with scope like this:
|
498
|
+
|
499
|
+
```ruby
|
500
|
+
Rails.application.routes.draw do
|
501
|
+
devise_for :users
|
502
|
+
# Integrated with Devise for different model, and use with scope
|
503
|
+
scope :admins, as: :admins do
|
504
|
+
notify_to :admins, with_devise: :users, devise_default_routes: true, routing_scope: :admins
|
505
|
+
end
|
506
|
+
end
|
507
|
+
```
|
508
|
+
|
509
|
+
Then, you can access */admins/notifications* instead of */admins/1/notifications*.
|
510
|
+
|
511
|
+
#### REST API backend with Devise Token Auth
|
512
|
+
|
513
|
+
We can also integrate [REST API backend](#rest-api-backend) with [Devise Token Auth](https://github.com/lynndylanhurley/devise_token_auth).
|
514
|
+
Use **:with_devise** option with **:api_mode** option *config/routes.rb* for the target like this:
|
515
|
+
|
516
|
+
```ruby
|
517
|
+
Rails.application.routes.draw do
|
518
|
+
devise_for :users
|
519
|
+
# Configure authentication API with Devise Token Auth
|
520
|
+
namespace :api do
|
521
|
+
scope :"v2" do
|
522
|
+
mount_devise_token_auth_for 'User', at: 'auth'
|
523
|
+
end
|
524
|
+
end
|
525
|
+
# Integrated with Devise Token Auth
|
526
|
+
scope :api do
|
527
|
+
scope :"v2" do
|
528
|
+
notify_to :users, api_mode: true, with_devise: :users, with_subscription: true
|
529
|
+
end
|
530
|
+
end
|
531
|
+
end
|
532
|
+
```
|
533
|
+
|
534
|
+
You can also configure it as simple default routes and with different model from Devise resource as a target:
|
535
|
+
|
536
|
+
```ruby
|
537
|
+
Rails.application.routes.draw do
|
538
|
+
devise_for :users
|
539
|
+
# Configure authentication API with Devise Token Auth
|
540
|
+
namespace :api do
|
541
|
+
scope :"v2" do
|
542
|
+
mount_devise_token_auth_for 'User', at: 'auth'
|
543
|
+
end
|
544
|
+
end
|
545
|
+
# Integrated with Devise Token Auth as simple default routes and with different model from Devise resource as a target
|
546
|
+
scope :api do
|
547
|
+
scope :"v2" do
|
548
|
+
scope :admins, as: :admins do
|
549
|
+
notify_to :admins, api_mode: true, with_devise: :users, devise_default_routes: true, with_subscription: true
|
550
|
+
end
|
551
|
+
end
|
552
|
+
end
|
553
|
+
end
|
554
|
+
```
|
555
|
+
|
556
|
+
Then *activity_notification* will use *[ActivityNotification::NotificationsApiWithDeviseController](/app/controllers/activity_notification/notifications_api_with_devise_controller.rb)* as a notifications controller. The controller actions automatically call *authenticate_user!* and the user will be restricted to access and operate own notifications only, not others'.
|
557
|
+
|
558
|
+
##### Configuring Devise Token Auth
|
559
|
+
|
560
|
+
At first, you have to set up [Devise Token Auth configuration](https://devise-token-auth.gitbook.io/devise-token-auth/config). You also have to configure your target model like this:
|
561
|
+
|
562
|
+
```ruby
|
563
|
+
class User < ActiveRecord::Base
|
564
|
+
devise :database_authenticatable, :confirmable
|
565
|
+
include DeviseTokenAuth::Concerns::User
|
566
|
+
acts_as_target
|
567
|
+
end
|
568
|
+
```
|
569
|
+
|
570
|
+
##### Using REST API backend with Devise Token Auth
|
571
|
+
|
572
|
+
To sign in and get *access-token* from Devise Token Auth, call *sign_in* API which you configured by *mount_devise_token_auth_for* method:
|
573
|
+
|
574
|
+
```console
|
575
|
+
$ curl -X POST -H "Content-Type: application/json" -D - -d '{"email": "ichiro@example.com","password": "changeit"}' https://activity-notification-example.herokuapp.com/api/v2/auth/sign_in
|
576
|
+
|
577
|
+
|
578
|
+
HTTP/1.1 200 OK
|
579
|
+
...
|
580
|
+
Content-Type: application/json; charset=utf-8
|
581
|
+
access-token: ZiDvw8vJGtbESy5Qpw32Kw
|
582
|
+
token-type: Bearer
|
583
|
+
client: W0NkGrTS88xeOx4VDOS-Xg
|
584
|
+
expiry: 1576387310
|
585
|
+
uid: ichiro@example.com
|
586
|
+
...
|
587
|
+
|
588
|
+
{
|
589
|
+
"data": {
|
590
|
+
"id": 1,
|
591
|
+
"email": "ichiro@example.com",
|
592
|
+
"provider": "email",
|
593
|
+
"uid": "ichiro@example.com",
|
594
|
+
"name": "Ichiro"
|
595
|
+
}
|
596
|
+
}
|
597
|
+
```
|
598
|
+
|
599
|
+
Then, call *activity_notification* API with returned *access-token*, *client* and *uid* as HTTP headers:
|
600
|
+
|
601
|
+
```console
|
602
|
+
$ curl -X GET -H "Content-Type: application/json" -H "access-token: ZiDvw8vJGtbESy5Qpw32Kw" -H "client: W0NkGrTS88xeOx4VDOS-Xg" -H "uid: ichiro@example.com" -D - https://activity-notification-example.herokuapp.com/api/v2/notifications
|
603
|
+
|
604
|
+
HTTP/1.1 200 OK
|
605
|
+
...
|
606
|
+
|
607
|
+
{
|
608
|
+
"count": 7,
|
609
|
+
"notifications": [
|
610
|
+
...
|
611
|
+
]
|
612
|
+
}
|
613
|
+
```
|
614
|
+
|
615
|
+
Without valid *access-token*, API returns *401 Unauthorized*:
|
616
|
+
|
617
|
+
```console
|
618
|
+
$ curl -X GET -H "Content-Type: application/json" -D - https://activity-notification-example.herokuapp.com/api/v2/notifications
|
619
|
+
|
620
|
+
HTTP/1.1 401 Unauthorized
|
621
|
+
...
|
622
|
+
|
623
|
+
{
|
624
|
+
"errors": [
|
625
|
+
"You need to sign in or sign up before continuing."
|
626
|
+
]
|
627
|
+
}
|
628
|
+
```
|
629
|
+
|
630
|
+
When you request restricted resources of unauthorized targets, *activity_notification* API returns *403 Forbidden*:
|
631
|
+
|
632
|
+
```console
|
633
|
+
$ curl -X GET -H "Content-Type: application/json" -H "access-token: ZiDvw8vJGtbESy5Qpw32Kw" -H "client: W0NkGrTS88xeOx4VDOS-Xg" -H "uid: ichiro@example.com" -D - https://activity-notification-example.herokuapp.com/api/v2/notifications/1
|
634
|
+
|
635
|
+
HTTP/1.1 403 Forbidden
|
636
|
+
...
|
637
|
+
|
638
|
+
{
|
639
|
+
"gem": "activity_notification",
|
640
|
+
"error": {
|
641
|
+
"code": 403,
|
642
|
+
"message": "Forbidden because of invalid parameter",
|
643
|
+
"type": "Wrong target is specified"
|
644
|
+
}
|
645
|
+
}
|
646
|
+
```
|
647
|
+
|
648
|
+
See [Devise Token Auth documents](https://devise-token-auth.gitbook.io/devise-token-auth/) for more details.
|
649
|
+
|
650
|
+
|
651
|
+
### Push notification with Action Cable
|
652
|
+
|
653
|
+
*activity_notification* supports push notification with Action Cable by WebSocket.
|
654
|
+
*activity_notification* only provides Action Cable channels implementation, does not connections.
|
655
|
+
You can use default implementaion in Rails or your custom `ApplicationCable::Connection` for Action Cable connections.
|
656
|
+
|
657
|
+
#### Enabling broadcasting notifications to channels
|
658
|
+
|
659
|
+
Broadcasting notifications to Action Cable channels is provided as [optional notification targets implementation](#action-cable-channels-as-optional-target).
|
660
|
+
This optional targets is disabled as default. You can configure it to enable Action Cable broadcasting in initializer *activity_notification.rb*.
|
661
|
+
|
662
|
+
```ruby
|
663
|
+
# Enable Action Cable broadcasting as HTML view
|
664
|
+
config.action_cable_enabled = true
|
665
|
+
# Enable Action Cable API broadcasting as formatted JSON
|
666
|
+
config.action_cable_api_enabled = true
|
667
|
+
```
|
668
|
+
|
669
|
+
You can also configure them for each model by *acts_as roles* like these:
|
670
|
+
|
671
|
+
```ruby
|
672
|
+
class User < ActiveRecord::Base
|
673
|
+
# Allow Action Cable broadcasting
|
674
|
+
acts_as_target action_cable_allowed: true
|
675
|
+
end
|
676
|
+
```
|
677
|
+
|
678
|
+
```ruby
|
679
|
+
class Comment < ActiveRecord::Base
|
680
|
+
belongs_to :article
|
681
|
+
belongs_to :user
|
682
|
+
|
683
|
+
acts_as_notifiable :users,
|
684
|
+
targets: ->(comment, key) {
|
685
|
+
([comment.article.user] + comment.article.reload.commented_users.to_a - [comment.user]).uniq
|
686
|
+
},
|
687
|
+
# Allow Action Cable broadcasting as HTML view
|
688
|
+
action_cable_allowed: true,
|
689
|
+
# Enable Action Cable API broadcasting as formatted JSON
|
690
|
+
action_cable_api_allowed: true
|
691
|
+
end
|
692
|
+
```
|
693
|
+
|
694
|
+
Then, *activity_notification* will broadcast configured notifications to target channels by *[ActivityNotification::OptionalTarget::ActionCableChannel](/lib/activity_notification/optional_targets/action_cable_channel.rb)* and/or *[ActivityNotification::OptionalTarget::ActionCableApiChannel](/lib/activity_notification/optional_targets/action_cable_api_channel.rb)* as optional targets.
|
695
|
+
|
696
|
+
#### Subscribing notifications from channels
|
697
|
+
|
698
|
+
*activity_notification* provides *[ActivityNotification::NotificationChannel](/app/channels/activity_notification/notification_channel.rb)* and *[ActivityNotification::NotificationApiChannel](/app/channels/activity_notification/notification_api_channel.rb)* to subscribe broadcasted notifications with Action Cable.
|
699
|
+
|
700
|
+
You can simply create subscriptions for the specified target in your view like this:
|
701
|
+
|
702
|
+
```js
|
703
|
+
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/push.js/1.0.9/push.min.js"></script>
|
704
|
+
<script>
|
705
|
+
App.activity_notification = App.cable.subscriptions.create(
|
706
|
+
{
|
707
|
+
channel: "ActivityNotification::NotificationChannel",
|
708
|
+
target_type: "<%= @target.to_class_name %>", target_id: "<%= @target.id %>"
|
709
|
+
},
|
710
|
+
{
|
711
|
+
connected: function() {
|
712
|
+
// Connected
|
713
|
+
},
|
714
|
+
disconnected: function() {
|
715
|
+
// Disconnected
|
716
|
+
},
|
717
|
+
rejected: function() {
|
718
|
+
// Rejected
|
719
|
+
},
|
720
|
+
received: function(notification) {
|
721
|
+
// Display notification
|
722
|
+
|
723
|
+
// Push notificaion using Web Notification API by Push.js
|
724
|
+
Push.create('ActivityNotification', {
|
725
|
+
body: notification.text,
|
726
|
+
timeout: 5000,
|
727
|
+
onClick: function () {
|
728
|
+
location.href = notification.notifiable_path;
|
729
|
+
this.close();
|
730
|
+
}
|
731
|
+
});
|
732
|
+
}
|
733
|
+
}
|
734
|
+
);
|
735
|
+
</script>
|
736
|
+
```
|
737
|
+
|
738
|
+
or create subscriptions in your single page application with API channels like this:
|
739
|
+
|
740
|
+
```js
|
741
|
+
// Vue.js implementation with actioncable-vue
|
742
|
+
export default {
|
743
|
+
// ...
|
744
|
+
mounted () {
|
745
|
+
this.subscribeActionCable();
|
746
|
+
},
|
747
|
+
channels: {
|
748
|
+
'ActivityNotification::NotificationApiChannel': {
|
749
|
+
connected() {
|
750
|
+
// Connected
|
751
|
+
},
|
752
|
+
disconnected() {
|
753
|
+
// Disconnected
|
754
|
+
},
|
755
|
+
rejected() {
|
756
|
+
// Rejected
|
757
|
+
},
|
758
|
+
received(data) {
|
759
|
+
this.notify(data);
|
760
|
+
}
|
761
|
+
}
|
762
|
+
},
|
763
|
+
methods: {
|
764
|
+
subscribeActionCable () {
|
765
|
+
this.$cable.subscribe({
|
766
|
+
channel: 'ActivityNotification::NotificationApiChannel',
|
767
|
+
target_type: this.target_type, target_id: this.target_id
|
768
|
+
});
|
769
|
+
},
|
770
|
+
notify (data) {
|
771
|
+
// Display notification
|
772
|
+
|
773
|
+
// Push notificaion using Web Notification API by Push.js
|
774
|
+
Push.create('ActivityNotification', {
|
775
|
+
body: data.notification.text,
|
776
|
+
timeout: 5000,
|
777
|
+
onClick: function () {
|
778
|
+
location.href = data.notification.notifiable_path;
|
779
|
+
this.close();
|
780
|
+
}
|
781
|
+
});
|
782
|
+
}
|
783
|
+
}
|
784
|
+
}
|
785
|
+
```
|
786
|
+
|
787
|
+
Then, *activity_notification* will push desktop notification using Web Notification API.
|
788
|
+
|
789
|
+
#### Subscribing notifications with Devise authentication
|
790
|
+
|
791
|
+
To use Devise integration, enable subscribing notifications with Devise authentication in initializer *activity_notification.rb*.
|
792
|
+
|
793
|
+
```ruby
|
794
|
+
config.action_cable_with_devise = true
|
795
|
+
```
|
796
|
+
|
797
|
+
You can also configure them for each target model by *acts_as_target* like this:
|
798
|
+
|
799
|
+
```ruby
|
800
|
+
class User < ActiveRecord::Base
|
801
|
+
acts_as_target action_cable_allowed: true,
|
802
|
+
# Allow Action Cable broadcasting and enable subscribing notifications with Devise authentication
|
803
|
+
action_cable_with_devise: true
|
804
|
+
end
|
805
|
+
```
|
806
|
+
|
807
|
+
When you set *action_cable_with_devise* option to *true*, *ActivityNotification::NotificationChannel* will reject your subscription requests for the target type.
|
808
|
+
|
809
|
+
*activity_notification* also provides *[ActivityNotification::NotificationWithDeviseChannel](/app/channels/activity_notification/notification_with_devise_channel.rb)* to create subscriptions integrated with Devise authentication.
|
810
|
+
You can simply use *ActivityNotification::NotificationWithDeviseChannel* instead of *ActivityNotification::NotificationChannel*:
|
811
|
+
|
812
|
+
```js
|
813
|
+
App.activity_notification = App.cable.subscriptions.create(
|
814
|
+
{
|
815
|
+
channel: "ActivityNotification::NotificationWithDeviseChannel",
|
816
|
+
target_type: "<%= @target.to_class_name %>", target_id: "<%= @target.id %>"
|
817
|
+
},
|
818
|
+
{
|
819
|
+
// ...
|
820
|
+
}
|
821
|
+
);
|
822
|
+
```
|
823
|
+
|
824
|
+
You can also create these subscriptions with *devise_type* parameter instead of *target_id* parameter like this:
|
825
|
+
|
826
|
+
```js
|
827
|
+
App.activity_notification = App.cable.subscriptions.create(
|
828
|
+
{
|
829
|
+
channel: "ActivityNotification::NotificationWithDeviseChannel",
|
830
|
+
target_type: "users", devise_type: "users"
|
831
|
+
},
|
832
|
+
{
|
833
|
+
// ...
|
834
|
+
}
|
835
|
+
);
|
836
|
+
```
|
837
|
+
|
838
|
+
*ActivityNotification::NotificationWithDeviseChannel* will confirm subscription requests from authenticated cookies by Devise. If the user has not signed in, the subscription request will be rejected. If the user has signed in as unauthorized user, the subscription request will be also rejected.
|
839
|
+
|
840
|
+
In addtion, you can use `Target#notification_action_cable_channel_class_name` method to select channel class depending on your *action_cable_with_devise* configuration for the target.
|
841
|
+
|
842
|
+
```js
|
843
|
+
App.activity_notification = App.cable.subscriptions.create(
|
844
|
+
{
|
845
|
+
channel: "<%= @target.notification_action_cable_channel_class_name %>",
|
846
|
+
target_type: "<%= @target.to_class_name %>", target_id: "<%= @target.id %>"
|
847
|
+
},
|
848
|
+
{
|
849
|
+
// ...
|
850
|
+
}
|
851
|
+
);
|
852
|
+
```
|
853
|
+
|
854
|
+
This script is also implemented in [default notifications index view](/app/views/activity_notification/notifications/default/index.html.erb) of *activity_notification*.
|
855
|
+
|
856
|
+
#### Subscribing notifications API with Devise Token Auth
|
857
|
+
|
858
|
+
To use Devise Token Auth integration, also enable subscribing notifications with Devise authentication in initializer *activity_notification.rb*.
|
859
|
+
|
860
|
+
```ruby
|
861
|
+
config.action_cable_with_devise = true
|
862
|
+
```
|
863
|
+
|
864
|
+
You can also configure them for each target model by *acts_as_target* like this:
|
865
|
+
|
866
|
+
```ruby
|
867
|
+
class User < ActiveRecord::Base
|
868
|
+
acts_as_target action_cable_api_allowed: true,
|
869
|
+
# Allow Action Cable broadcasting and enable subscribing notifications API with Devise Token Auth
|
870
|
+
action_cable_with_devise: true
|
871
|
+
end
|
872
|
+
```
|
873
|
+
|
874
|
+
When you set *action_cable_with_devise* option to *true*, *ActivityNotification::NotificationApiChannel* will reject your subscription requests for the target type.
|
875
|
+
|
876
|
+
*activity_notification* also provides *[ActivityNotification::NotificationApiWithDeviseChannel](/app/channels/activity_notification/notification_api_with_devise_channel.rb)* to create subscriptions integrated with Devise Token Auth.
|
877
|
+
You can simply use *ActivityNotification::NotificationApiWithDeviseChannel* instead of *ActivityNotification::NotificationApiChannel*. Note that you have to pass authenticated token by Devise Token Auth in subscription requests like this:
|
878
|
+
|
879
|
+
```js
|
880
|
+
export default {
|
881
|
+
// ...
|
882
|
+
channels: {
|
883
|
+
'ActivityNotification::NotificationApiWithDeviseChannel': {
|
884
|
+
// ...
|
885
|
+
}
|
886
|
+
},
|
887
|
+
methods: {
|
888
|
+
subscribeActionCable () {
|
889
|
+
this.$cable.subscribe({
|
890
|
+
channel: 'ActivityNotification::NotificationApiWithDeviseChannel',
|
891
|
+
target_type: this.target_type, target_id: this.target_id,
|
892
|
+
'access-token': this.authHeaders['access-token'],
|
893
|
+
'client': this.authHeaders['client'],
|
894
|
+
'uid': this.authHeaders['uid']
|
895
|
+
});
|
896
|
+
}
|
897
|
+
}
|
898
|
+
}
|
899
|
+
```
|
900
|
+
|
901
|
+
You can also create these subscriptions with *devise_type* parameter instead of *target_id* parameter like this:
|
902
|
+
|
903
|
+
```js
|
904
|
+
export default {
|
905
|
+
// ...
|
906
|
+
methods: {
|
907
|
+
subscribeActionCable () {
|
908
|
+
this.$cable.subscribe({
|
909
|
+
channel: 'ActivityNotification::NotificationApiWithDeviseChannel',
|
910
|
+
target_type: "users", devise_type: "users",
|
911
|
+
'access-token': this.authHeaders['access-token'],
|
912
|
+
'client': this.authHeaders['client'],
|
913
|
+
'uid': this.authHeaders['uid']
|
914
|
+
});
|
915
|
+
}
|
916
|
+
}
|
917
|
+
}
|
918
|
+
```
|
919
|
+
|
920
|
+
*ActivityNotification::NotificationWithDeviseChannel* will confirm subscription requests from authenticated token by Devise Token Auth. If the token is invalid, the subscription request will be rejected. If the token of unauthorized user is passed, the subscription request will be also rejected.
|
921
|
+
|
922
|
+
This script is also implemented in [notifications index in sample single page application](/spec/rails_app/app/javascript/components/notifications/Index.vue).
|
923
|
+
|
924
|
+
#### Subscription management of Action Cable channels
|
925
|
+
Since broadcasting notifications to Action Cable channels is provided as [optional notification targets implementation](#action-cable-channels-as-optional-target), you can manage subscriptions as *:action_cable_channel* and *:action_cable_api_channel* optional target. See [subscription management of optional targets](#subscription-management-of-optional-targets) for more details.
|
926
|
+
|
927
|
+
|
928
|
+
### Optional notification targets
|
929
|
+
|
930
|
+
*activity_notification* supports configurable optional notification targets like Amazon SNS, Slack, SMS and so on.
|
931
|
+
|
932
|
+
#### Configuring optional targets
|
933
|
+
|
934
|
+
*activity_notification* provides default optional target implementation for Amazon SNS and Slack.
|
935
|
+
You can develop any optional target classes which extends *ActivityNotification::OptionalTarget::Base*, and configure them to notifiable model by *acts_as_notifiable* like this:
|
936
|
+
|
937
|
+
```ruby
|
938
|
+
class Comment < ActiveRecord::Base
|
939
|
+
belongs_to :article
|
940
|
+
belongs_to :user
|
941
|
+
|
942
|
+
require 'activity_notification/optional_targets/amazon_sns'
|
943
|
+
require 'activity_notification/optional_targets/slack'
|
944
|
+
require 'custom_optional_targets/console_output'
|
945
|
+
acts_as_notifiable :admins, targets: [Admin.first].compact,
|
946
|
+
notifiable_path: :article_notifiable_path,
|
947
|
+
# Set optional target implementation class and initializing parameters
|
948
|
+
optional_targets: {
|
949
|
+
ActivityNotification::OptionalTarget::AmazonSNS => { topic_arn: 'arn:aws:sns:XXXXX:XXXXXXXXXXXX:XXXXX' },
|
950
|
+
ActivityNotification::OptionalTarget::Slack => {
|
951
|
+
webhook_url: 'https://hooks.slack.com/services/XXXXXXXXX/XXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXX',
|
952
|
+
slack_name: :slack_name, channel: 'activity_notification', username: 'ActivityNotification', icon_emoji: ":ghost:"
|
953
|
+
},
|
954
|
+
CustomOptionalTarget::ConsoleOutput => {}
|
955
|
+
}
|
956
|
+
|
957
|
+
def article_notifiable_path
|
958
|
+
article_path(article)
|
959
|
+
end
|
960
|
+
end
|
961
|
+
```
|
962
|
+
|
963
|
+
Write *require* statement for optional target implementation classes and set them with initializing parameters to *acts_as_notifiable*.
|
964
|
+
*activity_notification* will publish all notifications of those targets and notifiables to optional targets.
|
965
|
+
|
966
|
+
#### Customizing message format
|
967
|
+
|
968
|
+
Optional targets prepare publishing messages from notification instance using view template like rendering notifications.
|
969
|
+
As default, all optional targets use *app/views/activity_notification/optional_targets/default/base/_default.text.erb*.
|
970
|
+
You can customize this template by creating *app/views/activity_notification/optional_targets/<target_class_name>/<optional_target_class_name>/<notification_key>.text.(|erb|haml|slim|something_else)*.
|
971
|
+
For example, if you have a notification for *:users* target with *:key* set to *"notification.comment.reply"* and *ActivityNotification::OptionalTarget::AmazonSNS* optional target is configured, the gem will look for a partial in *app/views/activity_notification/optional_targets/users/amazon_sns/comment/_reply.text.erb*.
|
972
|
+
The gem will also look for templates whose *<target_class_name>* is *default*, *<optional_target_class_name>* is *base* and *<notification_key>* is *default*, which means *app/views/activity_notification/optional_targets/users/amazon_sns/_default.text.erb*, *app/views/activity_notification/optional_targets/users/base/_default.text.erb*, *app/views/activity_notification/optional_targets/default/amazon_sns/_default.text.erb* and *app/views/activity_notification/optional_targets/default/base/_default.text.erb*.
|
973
|
+
|
974
|
+
#### Action Cable channels as optional target
|
975
|
+
|
976
|
+
*activity_notification* provides **ActivityNotification::OptionalTarget::ActionCableChannel** and **ActivityNotification::OptionalTarget::ActionCableApiChannel** as default optional target implementation to broadcast notifications to Action Cable channels.
|
977
|
+
|
978
|
+
Simply write `require 'activity_notification/optional_targets/action_cable_channel'` or `require 'activity_notification/optional_targets/action_cable_api_channel'` statement in your notifiable model and set *ActivityNotification::OptionalTarget::ActionCableChannel* or *ActivityNotification::OptionalTarget::ActionCableApiChannel* to *acts_as_notifiable* with initializing parameters. If you don't specify initializing parameters *ActivityNotification::OptionalTarget::ActionCableChannel* and *ActivityNotification::OptionalTarget::ActionCableApiChannel* uses configuration in *ActivityNotification.config*.
|
979
|
+
|
980
|
+
```ruby
|
981
|
+
# Set Action Cable broadcasting as HTML view using optional target
|
982
|
+
class Comment < ActiveRecord::Base
|
983
|
+
require 'activity_notification/optional_targets/action_cable_channel'
|
984
|
+
acts_as_notifiable :admins, targets: [Admin.first].compact,
|
985
|
+
optional_targets: {
|
986
|
+
ActivityNotification::OptionalTarget::ActionCableChannel => { channel_prefix: 'admin_notification' }
|
987
|
+
}
|
988
|
+
end
|
989
|
+
```
|
990
|
+
|
991
|
+
```ruby
|
992
|
+
# Set Action Cable API broadcasting as formatted JSON using optional target
|
993
|
+
class Comment < ActiveRecord::Base
|
994
|
+
require 'activity_notification/optional_targets/action_cable_api_channel'
|
995
|
+
acts_as_notifiable :admins, targets: [Admin.first].compact,
|
996
|
+
optional_targets: {
|
997
|
+
ActivityNotification::OptionalTarget::ActionCableApiChannel => { channel_prefix: 'admin_notification_api' }
|
998
|
+
}
|
999
|
+
end
|
1000
|
+
```
|
1001
|
+
|
1002
|
+
#### Amazon SNS as optional target
|
1003
|
+
|
1004
|
+
*activity_notification* provides **ActivityNotification::OptionalTarget::AmazonSNS** as default optional target implementation for Amazon SNS.
|
1005
|
+
|
1006
|
+
First, add **aws-sdk** or **aws-sdk-sns** (>= AWS SDK for Ruby v3) gem to your Gemfile and set AWS Credentials for SDK (See [Configuring the AWS SDK for Ruby](https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/setup-config.html)).
|
1007
|
+
|
1008
|
+
```ruby
|
1009
|
+
gem 'aws-sdk', '~> 2'
|
1010
|
+
# --- or ---
|
1011
|
+
gem 'aws-sdk-sns', '~> 1'
|
1012
|
+
```
|
1013
|
+
|
1014
|
+
```ruby
|
1015
|
+
require 'aws-sdk'
|
1016
|
+
# --- or ---
|
1017
|
+
require 'aws-sdk-sns'
|
1018
|
+
|
1019
|
+
Aws.config.update(
|
1020
|
+
region: 'your_region',
|
1021
|
+
credentials: Aws::Credentials.new('your_access_key_id', 'your_secret_access_key')
|
1022
|
+
)
|
1023
|
+
```
|
1024
|
+
|
1025
|
+
Then, write `require 'activity_notification/optional_targets/amazon_sns'` statement in your notifiable model and set *ActivityNotification::OptionalTarget::AmazonSNS* to *acts_as_notifiable* with *:topic_arn*, *:target_arn* or *:phone_number* initializing parameters.
|
1026
|
+
Any other options for `Aws::SNS::Client.new` are available as initializing parameters. See [API Reference of Class: Aws::SNS::Client](http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/SNS/Client.html) for more details.
|
1027
|
+
|
1028
|
+
```ruby
|
1029
|
+
class Comment < ActiveRecord::Base
|
1030
|
+
require 'activity_notification/optional_targets/amazon_sns'
|
1031
|
+
acts_as_notifiable :admins, targets: [Admin.first].compact,
|
1032
|
+
optional_targets: {
|
1033
|
+
ActivityNotification::OptionalTarget::AmazonSNS => { topic_arn: 'arn:aws:sns:XXXXX:XXXXXXXXXXXX:XXXXX' }
|
1034
|
+
}
|
1035
|
+
end
|
1036
|
+
```
|
1037
|
+
|
1038
|
+
#### Slack as optional target
|
1039
|
+
|
1040
|
+
*activity_notification* provides **ActivityNotification::OptionalTarget::Slack** as default optional target implementation for Slack.
|
1041
|
+
|
1042
|
+
First, add **slack-notifier** gem to your Gemfile and create Incoming WebHooks in Slack (See [Incoming WebHooks](https://wemakejp.slack.com/apps/A0F7XDUAZ-incoming-webhooks)).
|
1043
|
+
|
1044
|
+
```ruby
|
1045
|
+
gem 'slack-notifier'
|
1046
|
+
```
|
1047
|
+
|
1048
|
+
Then, write `require 'activity_notification/optional_targets/slack'` statement in your notifiable model and set *ActivityNotification::OptionalTarget::Slack* to *acts_as_notifiable* with *:webhook_url* and *:target_username* initializing parameters. *:webhook_url* is created WebHook URL and required, *:target_username* is target's slack user name as String value, symbol method name or lambda function and is optional.
|
1049
|
+
Any other options for `Slack::Notifier.new` are available as initializing parameters. See [Github slack-notifier](https://github.com/stevenosloan/slack-notifier) and [API Reference of Class: Slack::Notifier](http://www.rubydoc.info/gems/slack-notifier/1.5.1/Slack/Notifier) for more details.
|
1050
|
+
|
1051
|
+
```ruby
|
1052
|
+
class Comment < ActiveRecord::Base
|
1053
|
+
require 'activity_notification/optional_targets/slack'
|
1054
|
+
acts_as_notifiable :admins, targets: [Admin.first].compact,
|
1055
|
+
optional_targets: {
|
1056
|
+
ActivityNotification::OptionalTarget::Slack => {
|
1057
|
+
webhook_url: 'https://hooks.slack.com/services/XXXXXXXXX/XXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXX',
|
1058
|
+
target_username: :slack_username, channel: 'activity_notification', username: 'ActivityNotification', icon_emoji: ":ghost:"
|
1059
|
+
}
|
1060
|
+
}
|
1061
|
+
end
|
1062
|
+
```
|
1063
|
+
|
1064
|
+
#### Developing custom optional targets
|
1065
|
+
|
1066
|
+
You can develop any custom optional targets.
|
1067
|
+
Custom optional target class must extend **ActivityNotification::OptionalTarget::Base** and override **initialize_target** and **notify** method.
|
1068
|
+
You can use **render_notification_message** method to prepare message from notification instance using view template.
|
1069
|
+
|
1070
|
+
For example, create *lib/custom_optional_targets/amazon_sns.rb* as follows:
|
1071
|
+
|
1072
|
+
```ruby
|
1073
|
+
module CustomOptionalTarget
|
1074
|
+
# Custom optional target implementation for mobile push notification or SMS using Amazon SNS.
|
1075
|
+
class AmazonSNS < ActivityNotification::OptionalTarget::Base
|
1076
|
+
require 'aws-sdk'
|
1077
|
+
|
1078
|
+
# Initialize method to prepare Aws::SNS::Client
|
1079
|
+
def initialize_target(options = {})
|
1080
|
+
@topic_arn = options.delete(:topic_arn)
|
1081
|
+
@target_arn = options.delete(:target_arn)
|
1082
|
+
@phone_number = options.delete(:phone_number)
|
1083
|
+
@sns_client = Aws::SNS::Client.new(options)
|
1084
|
+
end
|
1085
|
+
|
1086
|
+
# Publishes notification message to Amazon SNS
|
1087
|
+
def notify(notification, options = {})
|
1088
|
+
@sns_client.publish(
|
1089
|
+
topic_arn: notification.target.resolve_value(options.delete(:topic_arn) || @topic_arn),
|
1090
|
+
target_arn: notification.target.resolve_value(options.delete(:target_arn) || @target_arn),
|
1091
|
+
phone_number: notification.target.resolve_value(options.delete(:phone_number) || @phone_number),
|
1092
|
+
message: render_notification_message(notification, options)
|
1093
|
+
)
|
1094
|
+
end
|
1095
|
+
end
|
1096
|
+
end
|
1097
|
+
```
|
1098
|
+
|
1099
|
+
Then, you can configure them to notifiable model by *acts_as_notifiable* like this:
|
1100
|
+
|
1101
|
+
```ruby
|
1102
|
+
class Comment < ActiveRecord::Base
|
1103
|
+
require 'custom_optional_targets/amazon_sns'
|
1104
|
+
acts_as_notifiable :admins, targets: [Admin.first].compact,
|
1105
|
+
optional_targets: {
|
1106
|
+
CustomOptionalTarget::AmazonSNS => { topic_arn: 'arn:aws:sns:XXXXX:XXXXXXXXXXXX:XXXXX' }
|
1107
|
+
}
|
1108
|
+
end
|
1109
|
+
```
|
1110
|
+
|
1111
|
+
*acts_as_notifiable* creates optional target instances and calls *initialize_target* method with initializing parameters.
|
1112
|
+
|
1113
|
+
#### Subscription management of optional targets
|
1114
|
+
|
1115
|
+
*ActivityNotification::Subscription* model provides API to subscribe and unsubscribe optional notification targets. Call these methods with optional target name like this:
|
1116
|
+
|
1117
|
+
```ruby
|
1118
|
+
# Subscribe Acltion Cable channel for 'comment.reply' notifications
|
1119
|
+
user.find_or_create_subscription('comment.reply').subscribe_to_optional_target(:action_cable_channel)
|
1120
|
+
|
1121
|
+
# Subscribe Acltion Cable API channel for 'comment.reply' notifications
|
1122
|
+
user.find_or_create_subscription('comment.reply').subscribe_to_optional_target(:action_cable_api_channel)
|
1123
|
+
|
1124
|
+
# Unsubscribe Slack notification for 'comment.reply' notifications
|
1125
|
+
user.find_or_create_subscription('comment.reply').unsubscribe_to_optional_target(:slack)
|
1126
|
+
```
|
1127
|
+
|
1128
|
+
You can also manage subscriptions of optional targets by subscriptions REST API. See [REST API backend](#rest-api-backend) for more details.
|
1129
|
+
|
1130
|
+
You can see sample subscription management view in demo application here: *https://activity-notification-example.herokuapp.com/users/1/subscriptions*
|