HeyYou
Send multichannel notifications with one command. Сonvenient storage of notifications texts. Create your own channels. Registrate receiver and send notifications for him easy.
Requirements
- Ruby 2.5.0 min (rspec works with ruby 2.5.0, 2.6.0, 2.7.0)
- FCM - Gem send push notification using fcm gem. You need fcm server key to successful configure push notifications.
Installation
gem 'hey-you'
And then execute:
$ bundle
Or install it yourself as:
$ gem install hey-you
How to use
Configure
First, you must configure HeyYou. Example:
HeyYou::Config.configure do
config.data_source. = { collection_files: ['config/notifications.yml'] }
config.email.from = '[email protected]'
config.push.fcm_token = 'fcm_server_key'
end
Required settings
Options for gem base work.
Data Source
- config.data_source.source_class - Class implemented instance method
load_collections
returning hash (by defaultHeyYou::DataSource::Yaml
) - config.data_source.options - Arguments for source_class. This options will be passed to init
source_class
OR - config.data_source.source_instance - Instance of source class implemented
load_collections
Read more about data source in data source.d
Push
- config.push.fcm_token - Required setting for push channel. You can not send push messages if setting was not set. You should set it to equal your fcm server key. ##### Email
- config.email.from - Email address for send email notifications.
Optional settings
Additional options for configure your notifications.
Base
- config.splitter - Chars for split notification keys for
builder. Default:
.
- config.registered_channels - Avialable channels for your
applications. Default:
[:push, :email]
- config.require_all_channels - Boolean. If true, when data for channel will not found in
file collection, error will be raised. Default:
false
- config.localization - Boolean. If true, hey-you begin support I18n locales for notifications collection. Your
notifications for build should be nested in
I18n.locale
key. Default:false
. For example:
# config/initializers/hey-you.rb
HeyYou::Config.configure do
...
i18n_files = Rails.application.config.i18n.available_locales.map do |locale|
"config/notifications/#{locale}.yml"
end
config.data_source.options = { collection_files: i18n_files }
...
end
# config/notifications/en.yml
en:
any_key:
any_nested_key:
push:
title: Test hey you
body: Hey you, %{name}
email:
subject: Test hello
body: Hey you, %{name}
# config/notifications/ru.yml
ru:
any_key:
any_nested_key:
push:
title: Эй, ты!
body: Эй, ты, %{name}
email:
subject: Привет
body: Эй, ты, %{name}
# From your code:
I18n.locale = :ru
user.send_notification('any_key.any_nested_key', name: 'QNester') #=> send notification with body `Эй, ты, QNester`
I18n.locale = :en
user.send_notification('any_key.any_nested_key', name: 'QNester') #=> send notification with body `Hey you, QNester`
user.send_notification('any_key.any_nested_key', name: 'QNester', locale: :ru) #=> send notification with body `Эй, ты, QNester`
Push
- config.push.priority - priority level for your pushes. Default: high
- config.push.ttl - default time_to_live option for fcm. Default 60
- config.push.fcm_timeout - default timeout for fcm. Default 30 ##### Email
- config.email.layout - default layout for email letters.
- config.email.use_default_mailing - use default mail sending or use custom mailer classes
- config.email.default_mailer_class - default mailer class for email notifications
- config.email.default_mailer_method - default mailer_method for mailer_class
- config.email.default_delivery_method - expects, that mailer_method will build message and delivery_method will send it.
If you use ActionMailer you can set this option like
delivery_now
ordelivery_later
.
By default all letters will send as simple text.
Registrate receiver
You can registrate your application classes like receivers.
You can easy send notification for receiver with method
#send_notification
. For example:
class User < Model
extend HeyYou::Receiver
receive(
push: -> { push_token.value },
email: -> { email }
)
end
Class method #receive
will registrate your class User
as receiver. In arguments we must pass Hash instance where
keys - channels names as symbols, and values - procs for
fetching values required to send notification. For push channel
expected that proc will return receiver's fcm registration id. For
email expected that proc will return receiver's email address.
You can pass options and sending condition for receiver channels. You must pass proc with receive_data to :subject
key and options
pass to :options
key. if
key should be passed for sending condition:
class User < Model
extend HeyYou::Receiver
receive(
push: -> { push_token.value },
email: {
subject: -> { email },
if: -> { email_notifications? },
options: { mailer_class: UserMailer, mailer_method: :notify! }
}
)
end
If you pass correct procs in #receive
you can send notification
for your user like:
user = User.find(1)
user.send_notification('for_users.hello')
Last command will fetch notifications credentials for user instance and will try to send SMS, Push and Email for it. What argument we pass for method? This is string key for builder. Read next to understand it.
Sometimes you need send notification independent on user's notification settings. For this case you can use
force
option in #send_notification
:
user = User.find(1)
user.settings.update!(email_notifications: false)
user.send_notification('for_users.hello') #=> will not send notification
user.send_notification('for_users.hello', force: true) #=> will send notification
Build your notification
HeyYou Notification Builder - good system for store your notifications in one place. By default you need create yml file with follow format:
# config/notifications/collection.yml
any_key:
any_nested_key:
push:
title: Test hey you
body: Hey you, %{name}
email:
subject: Test hello
body: Hey you, %{name}
You should pass file path to config.collection_file
to load your notification texts.
Now you can send notification:
...
user.send_notification('any_key.any_nested_key', name: 'HeyYou')
This command with fetch notifications templates from your collection file for each channel and will try interpolate it. If you will not pass required interpolation keys then error will be raised. After successful interpolation notification will send for all available channels for receiver: 1) Send push via fcm 2) Send email
Data Source
Often we need store our notification text in another data source, not int yml files. HeyYou has flexible system for data source. All what you need - make your own provider source and pass it to config. For example:
class NotificationText < ApplicationRecord
def self.load_collections
# load colelctions from database to hash
# THIS METHOD MUST returns hash!
end
end
HeyYou::Config.configure do
# NotificationText is a rails model
config.data_source.source_instance = NotificationText
end
HeyYou will pull texts from database to memory with initialize your application after this configuration. Builder will build your texts successfully.
HeyYou by default contains only two data sources:
HeyYou::DataSource::Yaml
- for store notifications collections in data. For example:ruby HeyYou::Config.configure do config.data_source.source_class = HeyYou::DataSource::Yaml config.data_source.options = { collection_files: ['config/notifications.yml'] } end
HeyYou::DataSource::Hash
- store notification everywhere you want and pass to HeyYou only hashruby config.data_source.source_class = HeyYou::DataSource::Yaml config.data_source.options = { data: { welcome: { email: { ... }, push: { ... } } } }
Pay attention: for difference source we should pass difference options.
Send notification
Receiver not only one way to send notification. You can send it using HeyYou::Sender
.
Just use method #send
for HeyYou::Sender and pass notification key and to
options
like:
HeyYou::Sender.send!(
'any_key.any_nested_key',
to: {
push: 'fcm_registration_token',
email: '[email protected]'
},
name: 'HeyYou'
)
This command will process texts and send push and email to to
credentials.
Sender options
Only option
You can user some options for sender. You can send notification exclude
not required channels with option :only
like:
user.send_notification('any_key.any_nested_key', name: 'HeyYou', only: [:push])
It will send notification only with push channel. Email will be skipped.
Channels options
Channels options should pass to send method with associated channel names like:
user.send_notification(
'any_key.any_nested_key',
name: 'HeyYou',
email: { layout: 'layout' }
)
In this example we pass option for email channel. We decide specific layout for 'any_key.any_nested_key' notification.
Create your own channels
To create your custom channel you should create two classes:
- HeyYou::Builders::
- HeyYou::Channels::
You must extend your builder class from HeyYou::Builder::Base
and realize
class method #build
. In this method you should fetch notification data for
Your channel. For example:
class HeyYou::Builder::CustomNotifier < HeyYou::Builder::Base
class << self
attr_reader :header, :body, :icon
def build
@header = interpolate(ch_data['header'], )
@body = interpolate(ch_data['body'], )
@icon = [:icon] || interpolate(ch_data['icon'], )
end
end
end
Your notifications collection YAML file will contain next:
any_key:
any_nested_key:
push:
# ...
custom_notifier:
header: Hello
body: Hello, %{name}
icon: 'icons.klass'
To check your builder you can call
notifier_data = HeyYou::Builder.new('any_key.any_nested_key', name: 'HeyYou').custom_notifier
notifier_data # => Instance of HeyYou::Builder::CustomNotifier
notifier_data.header # => Hello
notifier_data.body # => Hello, HeyYou
notifier_data.icon # => 'icons.klass'
You must extend your channel class from HeyYou::Channels::Base
and
realize class method #send!
. This method pass two arguments: builder instance and to option.
Finally, you channel should look like:
class HeyYou::Channels::CustomNotifier < HeyYou::Channels::Base
class << self
def send!(builder, to:)
custom_notifier_client.(
text: builder.custom_notifier.text,
token: to
)
end
end
end
If your channel require some configurations you should create class
HeyYou::Config::<YOUR_CHANNEL_NAME>
, extend it with Configurable module and add
accessors for it. Example:
class HeyYou::Config::CustomNotifier
extend HeyYou::Config::Configurable
attr_accessor :secret_key
def client
YourProviderClass::Client.new(secret_key)
end
end
If your attr is required you can add checking it in your channel:
class HeyYou::Channels::CustomNotifier < HeyYou::Channels::Base
class << self
def send!(builder, to:)
return false unless credentials_present?
HeyYou::Config.instance.custom_notifier.client.(
text: builder.custom_notifier.text,
token: to
)
end
def required_credentials
[:secret_key]
end
end
end
#credentials_present?
method check exists required_credentials
in your channel config.
Now, when you will send notification, it will be send with your channel too.
Extensions
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/QNester/hey-you. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.