README.md in noticent-0.0.1.pre.pre vs README.md in noticent-0.0.1

- old
+ new

@@ -1,5 +1,7 @@ +<img src="http://cdn2-cloud66-com.s3.amazonaws.com/images/oss-sponsorship.png" width=150/> + # Noticent Noticent is a Ruby gem for user notification management. It is written to deliver a developer friendly way to managing application notifications in a typical web application. Many applications have user notification: sending emails when a task is done or support for webhooks or Slack upon certain events. Noticent makes it easy to write maintainable code for notification subscription and delivery in a typical web application. [![Codeship Status for cloud66-oss/noticent](https://app.codeship.com/projects/f5bd9b70-646f-0137-d7e7-7232cc99892f/status?branch=master)](https://app.codeship.com/projects/344893) @@ -91,16 +93,12 @@ ```ruby Noticent.configure do channel :email scope :account do - alert :new_signup do - notify :owner - end - alert :new_team_member do - notify :users - end + alert(:new_signup){ notify :owner} + alert(:new_team_member) { notify :users } end end ``` Now you'd need to tell Noticent how to send emails by creating an email channel. This can be done in `app/models/noticent/channels/email.rb`: @@ -193,24 +191,29 @@ product :product_foo product :product_buzz product :product_bar - scope :account do + scope :account, check_constructor: false do alert :new_user do applies.to :product_foo notify :users notify(:staff).on(:internal) notify :owners + + default true end end scope :comment do - alert :new_comment do + alert :new_comment, constructor_name: :some_constructor do applies.not_to :product_buzz notify :commenter - notify :auther + notify :author + + default true + default(false) { on(:email) } end alert :comment_updated do notify :commenter end end @@ -230,10 +233,15 @@ ```ruby account_payload = AccountPayload.new(1, user.first) Noticent.notify(:new_user, account_payload) ``` +While it is possible to define and use alert names as symbols, Noticent also creates a constant with the name of the alert under the `Noticent` namespace to help with the use of alert names. +By using the constants you can make sure alert names are free of typos. + +For example, if you have an alert called `some_event` then after configuration there will be a constant called `Noticent::ALERT_SOME_EVENT` available to use with the value `:some_event`. + ### Using Each Noticent Component #### Payload To understand how to use Noticent, it's important to know the conventions it uses. First, payloads: A payload is a class and should have methods named after each one of the recipient groups specified in the configuration. For example, if an alert should be sent to `users` then payload should have a method or attribute called `users`. This method is called at the point the notifications need to be sent to retrieve the recipients. It is up to you what each recipient is: it could be an email address (string) or the entire user object or an ID. Your channel class will be given this and should know how to handle it. @@ -248,10 +256,14 @@ end ``` If specified, the type of the payload is checked against this class at runtime (when `Notify` is called). +To enforce development type consistency payload should have class method constructors that are named after the alert names. This can be turned off by setting `check_constructor` on scopes to `false`. +To share the same class method constructor for different alerts, you can use the `constructor_name` on alert to tell Noticent to look for a constructor that is not named after the alert itself. +This is a validation step only and doesn't affect the performance of Noticent. + #### Channel Channels should be derived from `::Noticent::Channel` class and called the same as with the name of the channel with a `Channel` suffix: `email` would be `EmailChannel` and `slack` will be `SlackChannel`. Also, channels should have a method for each type of alert they are supposed to handle. Channel class can be changed using the `klass` argument during definition. Channels can also have groups. If no group is supplied, a channel will belong to the `default` group. Groups can be used to send alerts to a subset of channels: @@ -271,12 +283,27 @@ end end ``` In the example above, we are creating 2 flavors of the slack channel, one called `team_slack` but using the same class and configured differently. When `using` is used in a channel, any attribute passed into `using` will be called on the channel after creation with the given values. -For example, in this example, the `Slack` class is instantiated and attribute `fuzz` is set to `:buzz` on it before the alert method is called. +For example, in this example, the `Slack` class is instantiated and attribute `fuzz` is set to `:buzz` on it before the alert method is called. +You can use `on` with a channel name instead of a channel group name instead: + +```ruby +Noticent.configure do + channel :email + channel :private_emails, group: :internal + channel :slack + + alert :some_event do + notify(:users).on(:internal) # this is a group name + notify(:staff).on(:slack) # this is a channel name + end +end +``` + You can use `render` in the channel code to render and return the view file and its front matter (if available). By default, channel will look for `html` and `erb` as the file content and format. You can change these both when calling `render` or at the top of the controller: ```ruby class SlackChannel < ::Noticent::Channel default_format :json @@ -303,11 +330,11 @@ Views are like Rails views. Noticent supports rendering ERB files. You can also use layouts just like Rails. A layout is like a shared template `layout.html.erb`: ```html This is at the top -<%= yield %> +<%= @content %> This is at the bottom ``` `some_event.html.erb`: @@ -325,10 +352,32 @@ Noticent uses a combination of channel, alert and scope to determine if a recipient has subscribed to receive an alert or not. By default it uses the `ActiveRecordOptInProvider` class which uses a single database table for the process. You can write your own Opt-in provider if you want to store subscription (opt-in) state in a different place. See `ActiveRecordOptInProvider` for what such provider requires to operate. Use `Noticent.configuration.opt_in_provider`'s `opt_in`, `opt_out` and `opted_in?` methods to change the opt-in state of each recipient. +## Default Values + +You can specify a default opt-in value for each alert. By default alerts have a default value of `false` (no opt-in) unless this is globally changed (see Customization section). + +The default value for an alert can be set while this can also be changed per channel. For example: + +```ruby +Noticent.configure do + channel :email + channel :slack + channel :webhook + + scope :post do + alert :foo do + notify :users + default(true) # sets the default value for all channels for this alert to true + default(false) { on(:slack) } # sets the default value for this alert to false for the slack channel only + end + end +end +``` + ## Migration Noticent provides a method to add new alerts or remove deprecated alerts from the existing recipients. To add a new alert type, you can use `ActiveRecordOptInProvider.add_alert` method: ```ruby @@ -341,12 +390,22 @@ ```ruby Noticent.opt_in_provider.remove_alert(scope: :foo, alert_name: :some_old_alert) ``` -This removes all instances of the old alert from the opt-ins. +This removes all instances of the old alert from the opt-ins. +## New Recipient Sign up + +When a new recipient signs up, you might want to make sure they have all the default alerts setup for them. You can achieve this by calling `Noticent.setup_recipient`: + +```ruby +Noticent.setup_recipient(recipient_id: 1, scope: :post, entity_ids: [2]) +``` + +This will adds the default opt-ins for recipient 1 on all channels that are applicable to it on scope `post` for entity 2. + ## Validation Every time Noticent starts, it runs some validations on the configuration, classes that are defined, channels and alerts to make sure they are defined correctly and the supporting classes are in compliance with the requirements. ## Testing Your Alerts @@ -376,9 +435,15 @@ `opt_in_provider`: Opt-in provider class. Default is `ActiveRecordOptInProvider`. `logger`: Logger class. Default is `stdout` `halt_on_error`: Should notification fail after the first incident of an error during rendering. Default is `false` + +`default_value`: Default value for all alerts unless explicitly specified. Default is `false` + +`use_sub_modules`: If set to true, Noticent will look for Channel and Scope classes in sub modules under the `base_module_name`. +With `use_sub_modules` set to false, a channel named `:email` should be called `Noticent::Email` (if `base_module_name` is `Noticent`), while with `use_sub_modules` set to true, the same class should be `Noticent::Channels::Email`. +For Payloads, the sub module name will be `Payloads`. ## Development After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.