Integrates with your authentication solution to craft a personalized user notification platform.
NotificationSettings works with Rails 5 onwards. You can add it to your Gemfile
with:
gem 'notification-settings'
And then execute:
$ bundle
Or install it yourself as:
$ gem install notification-settings
Now run the generator:
$ rails g notification_handler:install
$ rails g notification_settings:install
To wrap things up, migrate the changes to your database:
$ rails db:migrate
First, you have to add some attributes to every model that acts as a notification_target
:
class User
# ...
notification_target
end
# A Hashie::Mash object that stores all the settings of a notification target.
add_column :users, :settings, :text
# A string that describes a notification-relevant state of a notification target.
add_column :users, :status, :string
NotificationSettings uses categories to allow your notification targets to define specific preferences. This is how you are able to specify the category
of a Notification
record:
notification = Notification.create(target: User.first, object: Recipe.first, category: :notification)
Note: The category
attribute of any new Notification
record will default to the default_category
configuration.
You can also scope records by their category:
# Return records with `'notification'` as category
Notification.notification_category
# Return records with `'follow'` as category
Notification.follow_category
You can completely disable notifications for a given notification target:
settings = User.first.settings
settings.enabled = false
This will prevent you from creating any new notifications with this user as target.
The default is true
(enabled) for this setting and the other settings.
A user can also have category-specific settings:
settings.categories!.send("#{category}!").enabled = false
He can have global or category-specific delivery method settings:
settings.delivery_methods!.enabled = false # Prevent delivering via *any* delivery method
settings.delivery_methods!.email!.enabled = false # Prevent delivering via the :email delivery method
settings.categories!.category!.delivery_methods!.email!.enabled = false # Prevent delivering via the :email delivery method for :category
NotificationSettings comes with three form objects that simplify building forms for updating settings.
The preferences form has just one attribute: enabled
. It can be used to update the global notification setting.
user = User.first
form = NotificationSettings::PreferencesForm.new(enabled: user.settings.enabled)
form.valid?
user.settings.enabled = form.enabled
The category preferences form has one attribute per category. It can be used to update category-specific settings.
user = User.first
form = NotificationSettings::CategoryPreferencesForm.new(user.settings.categories_.to_h)
form.valid?
form.changed_attributes.each do |category|
user.settings.categories!.send(category, form.send(category))
end
The delivery method preferences form has one attribute per category and a general enabled
attribute. It can be used to update delivery-method-specific settings or to disable all delivery methods.
user = User.first
form = NotificationSettings::DeliveryMethodPreferencesForm.new(user.settings.delivery_methods_.to_h)
form.valid?
form.changed_attributes.each do |delivery_method|
user.settings.delivery_methods!.send(delivery_method, form.send(delivery_method))
end
Subscriptions are a way to better handle settings for notifications from different objects to one notification target.
This is how to subscribe/unsubscribe a target to an object:
User.first.subscribe(Recipe.first)
User.first.unsubscribe(Recipe.first)
Now you can easily notify all subscribers from the subscribable object:
Recipe.first.notify_subscribers(delivery_method: :ActionMailer)
Let's assume that we have a group which has multiple chats. When sending notifications to subscribers of a given chat, we only want them to get notified. But when sending notifications about the group, we want to have everyone notified, that is either subscribed to the group or subscribed to one of its chats. To do that you have to add the private
method notification_dependents
to your model (in this case Group
) and return an array of ActiveRecord objects whose subscribers should receive notifications for objects of this class.
has_many :chats
has_many :talks
private
def notification_dependents
self.chats
end
It is possible to override that behavior when notifying subscribers:
# Disable notification dependents
Group.first.notify_subscribers(dependents: nil)
# Override notification dependents
Group.first.notify_subscribers(dependents: Group.first.chats + Group.first.talks)
You can customize settings & status for a single subscription just as you would for a notification target:
user = User.first
subscription = user.notification_subscriptions.first
subscription.settings.enabled = false
subscription.status = 'online'
subscription.save
You can add associations to your subscriber/subscribable classes if you need easy access to all their subscriptions:
# For subscribers:
# List all subscriptions of a subscriber
subscriber.notification_subscribables
# List all subscribables of a specific type a subscriber subscribed to
has_many :subscribed_products, through: :notification_subscribables, source: :subscribable, source_type: 'Product'
# For subscribables:
# List all subscriptions of a subscriber
subscribable.notification_subscribers
# List all subscribers of a specific type that subscribed to a subscribable
has_many :subscribed_users, through: :notification_subscribers, source: :subscriber, source_type: 'User'
NotificationSettings comes with a handy feature called Status. The status of a record can temporarily disable the ability to create notifications for or to push notifications of a target.
This is how to define a status:
User.first.update(status: 'do not disturb')
Note: You can set status
to any string you like.
status
has three possible values that are being used as defaults. Normally it defaults to 'online'
. If the last_seen
configuration option has been set, it can also default to 'idle'
or 'offline'
depending on the idle_after
and offline_after
configuration options.
If you have set status
to a custom value, you can get back to using the defaults by setting it back to nil
.
You can define statuses that prevent creating new notifications for a target and statuses that just prevent delivering them:
NotificationSettings.configure do |config|
config.do_not_notify_statuses = ['do not notify']
config.do_not_deliver_statuses = ['do not disturb']
end
You can configure NotificationSettings by passing a block to configure
. This can be done in config/initializers/notification-settings.rb
:
NotificationSettings.configure do |config|
config.categories = [:notification]
end
categories
Choose your default notification category. Takes an array of symbols. Defaults to [:notification]
.
default_category
Choose your default notification category. Takes a symbol. Defaults to :notification
.
idle_after
Time duration without activity after which the status defaults to 'idle'
. Takes a time. Defaults to 10.minutes
.
offline_after
Time duration without activity after which the status defaults to 'offline'
. Takes a time. Defaults to 3.hours
.
last_seen
Stringified datetime attribute name of object
that defines the time of the last activity. Takes a symbol. Defaults to :last_seen
.
statuses
Array of all possible statuses. Takes an array of strings. Defaults to ['online', 'idle', 'offline', 'do not notify', 'do not disturb']
.
do_not_notify_statuses
Array of possible statuses that will prevent creating notifications for a target. Takes an array of strings. Defaults to ['do not notify']
.
do_not_deliver_statuses
Array of possible statuses that will prevent delivering notifications of a target. Takes an array of strings. Defaults to ['do not disturb']
We use GitHub projects to coordinate the work on this project.
To propose your ideas, initiate the discussion by adding a new issue.
We hope that you will consider contributing to NotificationSettings. Please read this short overview for some information about how to get started:
Learn more about contributing to this repository, Code of Conduct
NotificationSettings follows Semantic Versioning 2.0 as defined at http://semver.org.