After using this gem in a few projects, I realized that all projects have different needs concerning the configuration of notifications (whether or not the user should received a notification or an email). We have apps which doesn't have the need for configuration so we are having a lots of Wupee::NotificationTypeConfiguration created and fetched from db for nothing. I really feel that the app should be responsible for addressing this. Also, in some apps, I had to reopen classes to override default behaviour of the gem or skip callbacks and adding others and I was feeling that something was wrong. See this issue for another example. Therefore, this branch removes all Wupee::NotificationTypeConfiguration but leaves a door open to customization, see Wupee initializer.
Wupee is a simple gem which tries to fill the gap of lacking gems to manage notifications in Rails app. Wupee is an opinionated solution which assumes that users needs to:
- be able to receive notifications in the app
- be able to receive notifications by email
The main object of the solution is the Wupee::Notification
which stores:
- receiver (polymorphic): the recipient of the message
- attached_object (polymorphic): the subject of the notification
- notification_type_id: a reference to a
Wupee::NotificationType
object - is_read: boolean
To use it, add it to your Gemfile:
gem 'wupee'
and bundle:
$ bundle
Run the generator, install migrations and migrate:
$ rails g wupee:install
$ rake wupee:install:migrations
$ rake db:migrate
Running the generator will do a few things:
- create wupee initializer:
# config/initializers/wupee.rb
Wupee.mailer = NotificationsMailer # the class of the mailer you will use to send the emails
Wupee.deliver_when = :now # use :later if you already configured a queuing system
# uncomment and implement your logic here to avoid/permit email sending to your users
# leave it commented if you always want your users received emails
# Wupee.email_sending_rule = Proc.new do |receiver, notification_type|
# # logic goes here, returning a boolean
# end
# uncomment and implement your logic here to avoid/permit email sending to your users
# leave it commented if you always want your users received notifications
# Wupee.notification_sending_rule = Proc.new do |receiver, notification_type|
# # logic goes here, returning a boolean
# end
- create a mailer
NotificationsMailer
which inheritates fromWupee::NotificationsMailer
# app/mailers/notifications_mailer.rb
class NotificationsMailer < Wupee::NotificationsMailer
default from: '[email protected]'
layout false
end
- adds wupee to your locale yml file (for email subjects)
# config/locales/en.yml
en:
wupee:
email_subjects:
rails g wupee:notification_type user_has_been_created
Will execute a few things:
- add an entry to your locale yml file :
en:
wupee:
email_subjects:
user_has_been_created: "user_has_been_created"
Feel free to edit the subject, you can put variables, example
...
user_has_been_created: "New user created: %{user_full_name}"
- create a json template for the notification:
json.subject ""
json.body ""
json.url ""
# none of this json attribute are mandatory!
In this template, you have access to the notification variable. You can customize it to fit your need, this is just an example.
- create an empty html template for the notification:
<!-- app/views/wupee/notifications/_user_has_been_created.html.erb -->
- You will have to create your email template as the generator doesn't create it.
For example, if your mailer is named
NotificationsMailer
, your template will take place inapp/views/notifications_mailer/user_has_been_created.html.erb
Including the concern Wupee::Receiver
in your receiver class (probably the User
class) permits a few things:
- get notifications of a user:
@user.notifications
- destroy
Wupee::Notification
associated to the receiver from db if it is destroyed
Including the concern Wupee::AttachedObject
in your attached object classe(s) permits a few things:
- get notifications associated to an attached object:
@attached_object.notifications_as_attached_object
- destroy
Wupee::Notification
associated to the attached object if it is destroyed
Imagine that you want to notify all admin that a new user signed up in your app and that you have a scope admin
in your User
class.
Wupee.notify do |n|
n.attached_object @the_new_user
n.notif_type :user_has_been_created # you can also pass an instance of a Wupee::NotificationType class to this method
n.subject_vars user_full_name: Proc.new { |notification| notification.attached_object.full_name } # variables to be interpolated the fill in the subject of the email (obviously optional)
n.locals extra_data: "something" # extra_data will be accessible in template as @locals[:extra_data]
n.receivers User.admin # you can use the method receiver instead of receivers for clarity if you pass only one instance of a receiver
n.deliver :now # you can overwrite global configuration here, optional
end
You can also use the method notify
this way:
Wupee.notify attached_object: @the_new_user, notif_type: :user_has_been_created, subject_vars: { user_full_name: Proc.new { |notification| notification.attached_object.full_name } }, locals: { extra_data: "Yeahhhhh" }, receivers: User.admin
The controller have various actions all scoped for the current user:
wupee/api/notifications#index
: fetch notifications, takes an optional get parameterscopes
(example: scopes=read,ordered)wupee/api/notifications#show
: fetch a notificationwupee/api/notifications#mark_as_read
: mark a notification as readwupee/api/notifications#mark_all_as_read
: mark all notifications as read
To use this controller, define a controller inheriting from Wupee::Api::NotificationsController
, set the routes in your config/routes.rb
and define a method current_user
which returns the user signed in.
Example:
# config/routes.rb
namespace :api, defaults: { format: :json } do
resources :notifications, only: [:index, :show] do
patch :mark_as_read, on: :member
patch :mark_all_as_read, on: :collection
end
end
# app/controllers/api/notifications_controller.rb
class Api::NotificationsController < Wupee::Api::NotificationsController
before_action :authenticate_user! # if you are using devise
end
What's UP SlEEde
This project rocks and uses MIT-LICENSE.