### Install Noticed Migrations Source: https://github.com/excid3/noticed/blob/main/UPGRADE.md Run this command to copy over the migrations for Noticed. ```bash rails noticed:install:migrations ``` -------------------------------- ### Install Noticed Gem and Database Migrations Source: https://context7.com/excid3/noticed/llms.txt Add the noticed gem to your Gemfile and run the generators to create the necessary database tables. ```bash # Add to Gemfile bundle add "noticed" # Copy and run migrations rails noticed:install:migrations rails db:migrate ``` -------------------------------- ### Add googleauth Gem Source: https://github.com/excid3/noticed/blob/main/docs/delivery_methods/fcm.md Install the 'googleauth' gem to enable FCM functionality. ```bash bundle add "googleauth" ``` -------------------------------- ### Example View Rendering of Notifications Source: https://context7.com/excid3/noticed/llms.txt Demonstrates how to iterate through user notifications and render them using the defined `notification_methods` like `icon`, `message`, and `url`. ```erb # In a view: @user.notifications.newest_first.each do |n| content_tag :div do link_to "#{n.icon} #{n.message}", n.url end end ``` -------------------------------- ### Add apnotic gem to project Source: https://github.com/excid3/noticed/blob/main/docs/delivery_methods/ios.md Install the apnotic gem using Bundler. ```bash bundle add "apnotic" ``` -------------------------------- ### Example I18n Translations for Notifier Source: https://context7.com/excid3/noticed/llms.txt Provides example translations for the `InvoicePaidNotifier`'s notification methods. These keys are automatically scoped under `notifiers..notification`. ```yaml # config/locales/en.yml # en: # notifiers: # invoice_paid_notifier: # notification: # message: "Your invoice for $%{amount} has been paid." ``` -------------------------------- ### Create Noticed Tables with UUIDs and Custom Fields Source: https://github.com/excid3/noticed/blob/main/README.md Example migration for creating `noticed_events` and `noticed_notifications` tables using UUIDs for IDs and including custom virtual columns derived from the `params` hash. ```ruby class CreateNoticedTables < ActiveRecord::Migration[7.1] def change create_table :noticed_events, id: :uuid do |t| t.string :type t.belongs_to :record, polymorphic: true, type: :uuid t.jsonb :params # Custom Fields t.string :organization_id, type: :uuid, as: "((params ->> 'organization_id')::uuid)", stored: true t.virtual :action_type, type: :string, as: "((params ->> 'action_type'))", stored: true t.virtual :url, type: :string, as: "((params ->> 'url'))", stored: true t.timestamps end create_table :noticed_notifications, id: :uuid do |t| t.string :type t.belongs_to :event, null: false, type: :uuid t.belongs_to :recipient, polymorphic: true, null: false, type: :uuid t.datetime :read_at t.datetime :seen_at t.timestamps end add_index :noticed_notifications, :read_at end end ``` -------------------------------- ### Configure iOS Delivery Method with Custom Formatting Source: https://github.com/excid3/noticed/blob/main/README.md This example demonstrates configuring the `:ios` delivery method with specific APNS (Apple Push Notification Service) formatting, including alert messages, custom payloads, and credentials. It also defines helper methods for retrieving credentials and device tokens. ```ruby class CommentNotifier < Noticed::Event deliver_by :ios do |config| config.format = :ios_format config.apns_key = :ios_cert config.key_id = :ios_key_id config.team_id = :ios_team_id config.bundle_identifier = Rails.application.credentials.dig(:ios, :bundle_identifier) config.device_tokens = :ios_device_tokens config.if = -> { recipient.send_ios_notification? } end def ios_format(apn) apn.alert = { title: title, body: body } apn.mutable_content = true apn.content_available = true apn.sound = "notification.m4r" apn.custom_payload = { url: url, type: self.class.name, id: record.id, image_url: "" || image_url, params: params.to_json } end def ios_cert(*) Rails.application.credentials.dig(:ios, Rails.env.to_sym, :apns_token_cert) end def ios_key_id(*) Rails.application.credentials.dig(:ios, Rails.env.to_sym, :key_id) end def ios_team_id(*) Rails.application.credentials.dig(:ios, Rails.env.to_sym, :team_id) end def ios_bundle_id(*) Rails.application.credentials.dig(:ios, Rails.env.to_sym, :bundle_identifier) end def ios_device_tokens(notification) notification.recipient.ios_device_tokens end def url comment_thread_path(record.thread) end end class Recipient < ApplicationRecord # or whatever your recipient model is has_many :ios_device_tokens def send_ios_notification? # some logic end end ``` -------------------------------- ### Customized Migration for Noticed Tables with UUIDs Source: https://context7.com/excid3/noticed/llms.txt Provides an example of a customized database migration for `noticed_events` and `noticed_notifications`. It uses UUIDs for primary keys and includes virtual columns for indexed fields derived from JSON parameters. ```ruby # Customized migration example class CreateNoticedTables < ActiveRecord::Migration[7.1] def change create_table :noticed_events, id: :uuid do |t| t.string :type t.belongs_to :record, polymorphic: true, type: :uuid t.jsonb :params t.integer :notifications_count # Virtual columns generated from params JSON t.virtual :organization_id, type: :string, as: "((params ->> 'organization_id')::uuid)", stored: true t.virtual :action_type, type: :string, as: "((params ->> 'action_type'))", stored: true t.timestamps end create_table :noticed_notifications, id: :uuid do |t| t.string :type t.belongs_to :event, null: false, type: :uuid t.belongs_to :recipient, polymorphic: true, null: false, type: :uuid t.datetime :read_at t.datetime :seen_at t.timestamps end add_index :noticed_notifications, :read_at end end ``` -------------------------------- ### ActionCable Connection Authentication Source: https://github.com/excid3/noticed/blob/main/docs/delivery_methods/action_cable.md Set up authentication for ActionCable connections to send notifications to individual users. This example uses Devise for authentication and requires `identified_by :current_user` in `ApplicationCable::Connection`. ```ruby module ApplicationCable class Connection < ActionCable::Connection::Base identified_by :current_user def connect self.current_user = find_verified_user logger.add_tags "ActionCable", "User #{current_user.id}" end protected def find_verified_user if current_user = env['warden'].user current_user else reject_unauthorized_connection end end end end ``` -------------------------------- ### Sending Notifications with Noticed Source: https://context7.com/excid3/noticed/llms.txt Examples of how to create and deliver notifications using `Notifier.with(...).deliver(recipients)`. Supports single or multiple recipients, ActiveJob options, and defining recipients within the notifier. ```ruby # Send to a single user NewCommentNotifier.with(record: @comment, post: @post).deliver(@comment.author) # Send to multiple recipients (uses insert_all for efficiency) NewCommentNotifier.with(record: @comment).deliver(User.subscribed) # Pass ActiveJob options (queue, wait, priority) NewCommentNotifier.with(record: @comment).deliver(User.all, queue: :critical, wait: 2.minutes) # Define recipients inside the notifier itself and call without arguments class NewCommentNotifier < ApplicationNotifier recipients -> { params[:record].thread.all_authors } end NewCommentNotifier.with(record: @comment).deliver ``` -------------------------------- ### Turbo Stream Custom Delivery Method Source: https://github.com/excid3/noticed/blob/main/README.md Example of a custom delivery method for sending notifications via Turbo Stream. It includes methods to broadcast updates to different targets. ```ruby # app/notifiers/delivery_methods/turbo_stream.rb class DeliveryMethods::TurboStream < ApplicationDeliveryMethod def deliver return unless recipient.is_a?(User) notification.broadcast_update_to_bell notification.broadcast_replace_to_index_count notification.broadcast_prepend_to_index_list end end ``` -------------------------------- ### Extend Noticed::Event with Load Hooks Source: https://context7.com/excid3/noticed/llms.txt Uses `ActiveSupport.on_load` to extend the `Noticed::Event` model. This example adds a `belongs_to` association for `account` and a custom `with` class method for instantiation. ```ruby # config/initializers/noticed.rb # Multitenancy: scope all events and notifications to an account ActiveSupport.on_load :noticed_event do belongs_to :account def self.with(params) account = params.delete(:account) || Current.account record = params.delete(:record) new(account: account, params: params, record: record) end def recipient_attributes_for(recipient) super.merge(account_id: account_id) end end ``` -------------------------------- ### Implement Fallback Notifications with Conditional Delivery Source: https://github.com/excid3/noticed/blob/main/README.md Combine multiple delivery methods with options like `wait` and `unless` to create fallback notification strategies. This example sends an email 15 minutes after an ActionCable notification if the notification hasn't been read. ```ruby class NewCommentNotifier < Noticed::Event deliver_by :action_cable deliver_by :email do |config| config.mailer = "CommentMailer" config.wait = 15.minutes config.unless = -> { read? } end end ``` -------------------------------- ### Extend Noticed::Notification with Load Hooks Source: https://context7.com/excid3/noticed/llms.txt Uses `ActiveSupport.on_load` to extend the `Noticed::Notification` model. This example adds a `belongs_to` association for `account` and a `delegate` for the `message` from the associated event. ```ruby ActiveSupport.on_load :noticed_notification do belongs_to :account delegate :message, to: :event scope :for_account, ->(account) { where(account: account) } end ``` -------------------------------- ### Model Associations for Noticed Source: https://context7.com/excid3/noticed/llms.txt Shows how to define `has_many` associations on ActiveRecord models to manage notifications from the recipient or record side. Includes examples for querying notifications and rendering them in ERB. ```ruby # Recipient side: user receives many notifications class User < ApplicationRecord has_many :notifications, as: :recipient, dependent: :destroy, class_name: "Noticed::Notification" end # Record side: query events generated by a specific object class Post < ApplicationRecord has_many :noticed_events, as: :record, dependent: :destroy, class_name: "Noticed::Event" has_many :notifications, through: :noticed_events, class_name: "Noticed::Notification" end # Querying notifications for params (cross-database compatible) class Comment < ApplicationRecord has_noticed_notifications # generates notifications_as_comment has_noticed_notifications param_name: :author, # generates notifications_as_author destroy: false # skip before_destroy callback end comment.notifications_as_comment # all events where params[:comment] = this comment author.notifications_as_author # all events where params[:author] = this user # Render in ERB @user.notifications.newest_first.limit(20).each do |notification| link_to notification.message, notification.url end ``` -------------------------------- ### Configure Shared Delivery Method Options Source: https://context7.com/excid3/noticed/llms.txt Demonstrates configuring universal delivery options such as `if`, `unless`, `wait`, `wait_until`, and `queue` for different delivery methods like Action Cable, Email, and SMS. ```ruby class InvoicePaidNotifier < ApplicationNotifier deliver_by :action_cable do |config| config.message = -> { { event: "invoice_paid", amount: params[:amount] } } end deliver_by :email do |config| config.mailer = "BillingMailer" config.method = :invoice_paid config.if = -> { recipient.email_notifications? } config.wait = 5.minutes # delay job enqueue config.unless = -> { read? } # skip if already read config.queue = :low_priority end deliver_by :sms, class: "Noticed::DeliveryMethods::TwilioMessaging" do |config| config.wait_until = -> { 9.am.tomorrow } # specific future time config.unless = :opted_out_of_sms? end notification_methods do def opted_out_of_sms?(notification) notification.recipient.sms_opt_out? end end end ``` -------------------------------- ### Run Tests Against Multiple Databases Source: https://github.com/excid3/noticed/blob/main/README.md Execute tests using different database adapters by setting the `DATABASE_URL` environment variable. ```bash DATABASE_URL=sqlite3:noticed_test rails test ``` ```bash DATABASE_URL=trilogy://root:@127.0.0.1/noticed_test rails test ``` ```bash DATABASE_URL=postgres://127.0.0.1/noticed_test rails test ``` -------------------------------- ### Declaring Required Parameters for Notifiers Source: https://context7.com/excid3/noticed/llms.txt Use `required_params` to enforce the presence of specific parameters during notification delivery. Includes an example of validating the `record` itself. ```ruby class CarSaleNotifier < ApplicationNotifier deliver_by :email do |config| config.mailer = "SalesMailer" config.method = :sale_confirmation end required_params :branch, :sale_price validates :record, presence: true # validates the polymorphic :record notification_methods do def message "Car sold for #{params[:sale_price]} at #{params[:branch].name}" end end end # Raises Noticed::ValidationError: CarSaleNotifier.with(record: @car).deliver(@salesperson) #=> Noticed::ValidationError: Param `branch` is required for CarSaleNotifier # OK: CarSaleNotifier.with(record: @car, branch: @branch, sale_price: 25_000).deliver(@salesperson) ``` -------------------------------- ### Generate Noticed Migrations Source: https://github.com/excid3/noticed/blob/main/README.md After adding the gem, generate and run the necessary database migrations. ```bash rails noticed:install:migrations rails db:migrate ``` -------------------------------- ### ActionMailer::Preview for Email Delivery Source: https://github.com/excid3/noticed/blob/main/docs/delivery_methods/email.md Set up ActionMailer::Preview to test email notifications. Use `YourMailer.with({ recipient: user }).mailer_method_name` to define the preview, ensuring the `recipient` key is present. ```ruby # test/mailers/previews/comment_mailer_preview.rb class CommentMailerPreview < ActionMailer::Preview def mailer_method_name CommentMailer.with({ recipient: User.first }).mailer_method_name end end ``` -------------------------------- ### Configure Action Cable Delivery Method Source: https://github.com/excid3/noticed/blob/main/UPGRADE.md Define Action Cable delivery options within the event block. The `stream` and `message` configurations can be set using lambdas. ```ruby class CommentNotifier < Noticed::Event deliver_by :action_cable do |config| config.channel = "NotificationChannel" config.stream = ->{ recipient } config.message = :to_websocket end def to_websocket(notification) { foo: :bar } end end ``` -------------------------------- ### Prevent Job Enqueuing with `before_enqueue` Source: https://github.com/excid3/noticed/blob/main/README.md Utilize the `before_enqueue` option to prevent a delivery job from being enqueued based on certain conditions. This example aborts the job if the recipient is not registered for iOS notifications. ```ruby class IosNotifier < Noticed::Event deliver_by :ios do |config| # ... config.before_enqueue = ->{ throw(:abort) unless recipient.registered_ios? } end end ``` -------------------------------- ### Extend Noticed Models in Application Configuration Source: https://github.com/excid3/noticed/blob/main/README.md Alternative method for extending Noticed models by placing the `to_prepare` block in `config/application.rb` when concerns are in separate files. ```ruby # config/application.rb module MyApp class Application < Rails::Application # ... config.to_prepare do Noticed::Event.include EventExtensions Noticed::Notification.include NotificationExtensions end end end ``` -------------------------------- ### Twilio Messaging Error Handling Source: https://github.com/excid3/noticed/blob/main/docs/delivery_methods/twilio_messaging.md Implement custom error handling for Twilio API responses. This example shows how to parse the error body and handle specific Twilio error codes. ```ruby deliver_by :twilio_messaging do |config| config.error_handler = lambda do |twilio_error_response| error_hash = JSON.parse(twilio_error_response.body) case error_hash["code"] when 21211 # The 'To' number is not a valid phone number. # Write your error handling code else raise "Unhandled Twilio error: #{error_hash}" end end end ``` -------------------------------- ### Generate Bulk Custom Delivery Methods Source: https://github.com/excid3/noticed/blob/main/README.md Use the `--bulk` flag with the generator to create delivery methods designed for bulk operations. ```bash rails generate noticed:delivery_method Discord --bulk ``` -------------------------------- ### Conditionally Deliver Notifications with `if:` Source: https://github.com/excid3/noticed/blob/main/README.md Use the `if:` option within a `deliver_by` block to conditionally send notifications based on recipient preferences. This example skips email delivery if the recipient has disabled email notifications. ```ruby class CommentNotifier < Noticed::Event deliver_by :email do |config| config.mailer = 'CommentMailer' config.method = :new_comment config.if = ->{ recipient.email_notifications? } end end ``` -------------------------------- ### Generate Custom Delivery Method Source: https://github.com/excid3/noticed/blob/main/README.md Use this command to generate a new custom delivery method class. Specify the name of the service you want to integrate with. ```bash rails generate noticed:delivery_method Discord ``` -------------------------------- ### Configure delivery for production iOS devices Source: https://github.com/excid3/noticed/blob/main/docs/delivery_methods/ios.md Configure a delivery method for sending notifications to production iOS devices, specifying production environment tokens. ```ruby deliver_by :ios do |config| config.device_tokens = -> { recipient.notification_tokens.where(environment: :production, platform: :iOS).pluck(:token) } end ``` -------------------------------- ### Use Translations in Notification Messages Source: https://github.com/excid3/noticed/blob/main/README.md Leverage Rails' `translate` (`t`) helper within your notification methods to easily manage localized messages. Keys starting with a period are automatically scoped to `notifiers..notification`. ```ruby class NewCommentNotifier < Noticed::Event # ... notification_methods do def message t(".message") end end # ... end ``` ```erb <%= @user.notifications.last.message %> ``` ```yaml # ~/config/locales/en.yml en: notifiers: new_comment_notifier: notification: message: "Someone posted a new comment!" ``` -------------------------------- ### Configure iOS delivery with token authentication Source: https://github.com/excid3/noticed/blob/main/docs/delivery_methods/ios.md Set up the iOS delivery method within an ApplicationNotifier, configuring device tokens, custom payload formatting, and authentication credentials. ```ruby class CommentNotifier < ApplicationNotifier deliver_by :ios do |config| config.device_tokens = -> { recipient.notification_tokens.where(platform: :iOS).pluck(:token) } config.format = ->(apn) { apn.alert = "Hello world" apn.custom_payload = {url: root_url(host: "example.org")} } config.bundle_identifier = Rails.application.credentials.dig(:ios, :bundle_id) config.key_id = Rails.application.credentials.dig(:ios, :key_id) config.team_id = Rails.application.credentials.dig(:ios, :team_id) config.apns_key = Rails.application.credentials.dig(:ios, :apns_key) config.error_handler = ->(exception) { ... } end end ``` -------------------------------- ### Readable Concern for Notification State Source: https://context7.com/excid3/noticed/llms.txt Demonstrates the `Readable` concern for `Noticed::Notification`, providing scopes and methods to manage `read_at` and `seen_at` timestamps. Includes examples for querying notification states and performing bulk updates. ```ruby # Scopes user.notifications.read # read_at IS NOT NULL user.notifications.unread # read_at IS NULL user.notifications.seen # seen_at IS NOT NULL user.notifications.unseen # seen_at IS NULL # Bulk class methods (UPDATE ... WHERE) user.notifications.unread.mark_as_read # sets read_at on all unread user.notifications.mark_as_read_and_seen # sets both timestamps user.notifications.mark_as_unread # clears read_at user.notifications.mark_as_seen # sets seen_at only # Instance methods notification.mark_as_read # returns false on failure notification.mark_as_read! # raises on failure notification.mark_as_unread notification.mark_as_seen notification.mark_as_unseen notification.read? # => true / false notification.unread? notification.seen? notification.unseen? ``` ```ruby # Fallback email after 15 minutes if not yet read class NewCommentNotifier < ApplicationNotifier deliver_by :action_cable do |config| config.message = -> { { body: params[:comment].body } } end deliver_by :email do |config| config.mailer = "CommentMailer" config.method = :new_comment config.wait = 15.minutes config.unless = -> { read? } end end ``` -------------------------------- ### Bluesky Bulk Delivery Method Source: https://context7.com/excid3/noticed/llms.txt Creates a post on Bluesky (AT Protocol) using identifier/password authentication. Requires `identifier`, `password`, and `json` configuration. ```ruby class AnnouncementNotifier < ApplicationNotifier bulk_deliver_by :bluesky do |config| config.identifier = ENV["BLUESKY_HANDLE"] # e.g. "myapp.bsky.social" config.password = ENV["BLUESKY_PASSWORD"] config.json = -> { { text: "📦 #{params[:version]} just shipped! #{params[:release_url]}", createdAt: Time.current.iso8601 } } # config.host = "bsky.social" # defaults to bsky.social end end ``` -------------------------------- ### Extract and Include Delivery Method Configurations Source: https://github.com/excid3/noticed/blob/main/README.md Reuse delivery method configurations across multiple Notifiers by defining them in modules and including those modules. This promotes DRY principles and simplifies maintenance. ```ruby # /app/notifiers/notifiers/comment_notifier.rb class CommentNotifier < Noticed::Event include IosNotifier include AndroidNotifier include EmailNotifier validates :record, presence: true end ``` ```ruby # /app/notifiers/concerns/ios_notifier.rb module IosNotifier extend ActiveSupport::Concern included do deliver_by :ios do |config| config.device_tokens = ->(recipient) { recipient.notification_tokens.where(platform: :iOS).pluck(:token) } config.format = ->(apn) { apn.alert = "Hello world" apn.custom_payload = {url: root_url(host: "example.org")} } config.bundle_identifier = Rails.application.credentials.dig(:ios, :bundle_id) config.key_id = Rails.application.credentials.dig(:ios, :key_id) config.team_id = Rails.application.credentials.dig(:ios, :team_id) config.apns_key = Rails.application.credentials.dig(:ios, :apns_key) config.if = -> { recipient.ios_notifications? } end end end ``` -------------------------------- ### Callbacks for Custom Delivery Methods Source: https://github.com/excid3/noticed/blob/main/README.md Implement `before_deliver`, `around_deliver`, or `after_deliver` callbacks within your custom delivery method to execute logic before, around, or after the notification is sent. ```ruby class DeliveryMethods::Discord < Noticed::DeliveryMethod after_deliver do # Do whatever you want end end ``` -------------------------------- ### Configure delivery for development (sandbox) iOS devices Source: https://github.com/excid3/noticed/blob/main/docs/delivery_methods/ios.md Configure a separate delivery method for sending notifications to development (sandbox) iOS devices, enabling the development environment and specifying sandbox tokens. ```ruby deliver_by :ios_development, class: "Noticed::DeliveryMethods::Ios" do |config| config.development = true config.device_tokens = ->{ recipient.notification_tokens.where(environment: :development, platform: :iOS).pluck(:token) } end ``` -------------------------------- ### Configure Bluesky Bulk Delivery Source: https://github.com/excid3/noticed/blob/main/docs/bulk_delivery_methods/bluesky.md Configure the Bluesky delivery method with your username, password, and a JSON payload for the post. The `json` block should return a hash that will be sent as the post content. ```ruby class CommentNotification bulk_deliver_by :bluesky do |config| config.identifier = "username" config.password = "password" config.json = -> { { text: "Hello world!", createdAt: Time.current.iso8601 # ... } } end end ``` -------------------------------- ### ActionCable Delivery Method Source: https://context7.com/excid3/noticed/llms.txt Pushes a real-time WebSocket message to the recipient via ActionCable. Requires `config.message`. ```APIDOC ## deliver_by :action_cable ### Description Pushes a real-time WebSocket message to the recipient via ActionCable. Requires `config.message`. ### Configuration Options - **channel**: Defaults to `Noticed::NotificationChannel`. Specifies the ActionCable channel to use. - **stream**: Defaults to `recipient`. A lambda or symbol to identify the stream. - **message**: A lambda or symbol that returns the message payload to be sent. ### Request Example ```ruby class NewMessageNotifier < ApplicationNotifier deliver_by :action_cable do |config| config.channel = "NotificationsChannel" config.stream = -> { recipient } config.message = -> { { type: "new_message", id: id, body: params[:message].body, sender: params[:sender].name, unread: recipient.notifications.unread.count } } end end ``` ``` -------------------------------- ### Configure Slack Delivery Method Source: https://github.com/excid3/noticed/blob/main/docs/delivery_methods/slack.md Configure the Slack delivery method by setting the URL and customizing the JSON payload. The `raise_if_not_ok` option can be set to `false` to disable checks for Slack's response. ```ruby class CommentNotification deliver_by :slack do |config| config.url = "https://slack.com..." config.json = -> { { # ... } } # Slack's chat.postMessage endpoint returns a 200 with {ok: true/false}. Disable this check by setting to false # config.raise_if_not_ok = true end end ``` -------------------------------- ### Configure Test Delivery Method Source: https://github.com/excid3/noticed/blob/main/docs/delivery_methods/test.md Configure a notification class to use the test delivery method by specifying `deliver_by :test`. ```ruby class CommentNotification deliver_by :test end ``` -------------------------------- ### FCM Credentials as String Path Source: https://github.com/excid3/noticed/blob/main/docs/delivery_methods/fcm.md Configure FCM credentials using a string path to the JSON key file. The path is automatically joined with Rails.root. ```ruby deliver_by :fcm do |config| config.credentials = "config/credentials/fcm.json" end ``` -------------------------------- ### Configure Email Delivery Source: https://github.com/excid3/noticed/blob/main/docs/delivery_methods/email.md Configure the email delivery method with mailer, method, and parameters. Use `params`, `args`, and `kwargs` to customize the mailer method call. `enqueue` defaults to false as deliveries are already job-based. ```ruby deliver_by :email do |config| config.mailer = "UserMailer" config.method = :invoice_paid config.params = ->{ params } config.args = ->{ [1, 2, 3] } config.kwargs = ->{ {body: "Hey there", subject: "Thanks for joining"} } # Enqueues a separate job for sending the email using deliver_later. # Deliveries already happen in jobs so this is typically unnecessary. # config.enqueue = false end ``` -------------------------------- ### Define Custom Delivery Method Class Source: https://github.com/excid3/noticed/blob/main/README.md Implement the `deliver` method in your custom delivery method class to handle the notification sending logic. Use `required_options` to specify configuration parameters. ```ruby class DeliveryMethods::Discord < ApplicationDeliveryMethod # Specify the config options your delivery method requires in its config block required_options # :foo, :bar def deliver # Logic for sending the notification end end ``` -------------------------------- ### ActionCable Delivery Method Configuration Source: https://context7.com/excid3/noticed/llms.txt Configures the ActionCable delivery method to push real-time WebSocket messages. Requires `config.message` and optionally `config.channel` and `config.stream`. ```ruby class NewMessageNotifier < ApplicationNotifier deliver_by :action_cable do |config| config.channel = "NotificationsChannel" # defaults to Noticed::NotificationChannel config.stream = -> { recipient } # defaults to recipient config.message = -> { { type: "new_message", id: id, body: params[:message].body, sender: params[:sender].name, unread: recipient.notifications.unread.count } } end end ``` ```javascript consumer.subscriptions.create("NotificationsChannel", { received(data) { renderNotification(data) } }) ``` -------------------------------- ### Use Custom Delivery Method in Notification Source: https://github.com/excid3/noticed/blob/main/README.md Integrate your custom delivery method into a notification class by adding a `deliver_by` line with a unique name and the class option. ```ruby class MyNotifier < Noticed::Event deliver_by :discord, class: "DeliveryMethods::Discord" end ``` -------------------------------- ### Configure Action Push Native Delivery Source: https://github.com/excid3/noticed/blob/main/docs/delivery_methods/action_push_native.md Configure the `action_push_native` delivery method within an ApplicationNotifier. Specify device retrieval, notification format, and platform-specific options. ```ruby class CommentNotifier < ApplicationNotifier deliver_by :action_push_native do |config| config.devices = -> { ApplicationPushDevice.where(owner: recipient) } config.format = -> { { title: "Hello world, #{recipient.first_name}!", body: "Welcome to Noticed with Action Push Native.", badge: 1, } } config.with_apple = -> { { category: "observable" } } config.with_google = -> { { } } config.with_data = -> { { } } end end ``` -------------------------------- ### Generate a Notifier Source: https://github.com/excid3/noticed/blob/main/README.md Use this command to generate a new Notifier class for your application. ```bash rails generate noticed:notifier NewCommentNotifier ``` -------------------------------- ### Configure ActionCable Delivery Source: https://github.com/excid3/noticed/blob/main/docs/delivery_methods/action_cable.md Configure the ActionCable delivery method with custom channel, stream, and message options. The `stream` and `message` options accept procs for dynamic configuration. ```ruby deliver_by :action_cable do |config| config.channel = "Noticed::NotificationChannel" config.stream = ->{ recipient } config.message = ->{ params.merge( user_id: recipient.id) end ``` -------------------------------- ### Add Noticed Gem to Gemfile Source: https://github.com/excid3/noticed/blob/main/README.md Run this command to add the Noticed gem to your application's Gemfile. ```ruby bundle add "noticed" ``` -------------------------------- ### Configure Push Notification Delivery Method Source: https://context7.com/excid3/noticed/llms.txt Defines a custom delivery method for sending push notifications. It includes before and after delivery callbacks and specifies required options like device token and title. ```ruby class DeliveryMethods::PushNotification < ApplicationDeliveryMethod required_options :device_token, :title before_deliver { Rails.logger.info "Sending push to #{evaluate_option(:device_token)}" } after_deliver { Rails.logger.info "Push sent successfully" } def deliver token = evaluate_option(:device_token) title = evaluate_option(:title) body = evaluate_option(:body) || "" MyPushService.send(token: token, title: title, body: body) end end ``` -------------------------------- ### Webhook Bulk Delivery Method Source: https://context7.com/excid3/noticed/llms.txt Sends an HTTP POST to any endpoint. Supports JSON, form-encoded, and raw body payloads. Requires `config.url` and optionally `config.json`, `config.headers`, `config.basic_auth`, `config.form`, or `config.body`. ```ruby class OrderCreatedNotifier < ApplicationNotifier bulk_deliver_by :webhook do |config| config.url = "https://hooks.zapier.com/hooks/catch/abc/xyz/" config.json = -> { { order_id: record.id, total: params[:total], customer: params[:customer].email } } config.headers = -> { { "X-Secret" => Rails.application.credentials.zapier[:secret] } } # config.basic_auth = -> { { user: "admin", pass: "secret" } } # config.form = -> { { field: value } } # config.body = -> { custom_body_string } end end ``` -------------------------------- ### Query Notifications by JSON Parameters (PostgreSQL) Source: https://github.com/excid3/noticed/blob/main/UPGRADE.md For PostgreSQL databases, use the `@>` operator to query notifications based on their JSON `params` column. ```ruby # Define the param_name = "user" # PostgreSQL model.where("params @> ?", Noticed::Coder.dump(param_name.to_sym => self).to_json) ``` -------------------------------- ### NewCommentNotifier Configuration and Methods Source: https://context7.com/excid3/noticed/llms.txt Defines delivery methods (ActionCable, email) and notification methods (`message`, `url`) for the `NewCommentNotifier`. ```ruby # app/notifiers/new_comment_notifier.rb class NewCommentNotifier < ApplicationNotifier deliver_by :action_cable do |config| config.channel = "NotificationsChannel" config.stream = -> { recipient } config.message = -> { { type: "new_comment", body: params[:comment].body } } end deliver_by :email do |config| config.mailer = "CommentMailer" config.method = :new_comment config.if = -> { recipient.email_notifications? } end notification_methods do def message t(".message") # looks up en.notifiers.new_comment_notifier.notification.message end def url post_path(record) end end end ``` -------------------------------- ### Custom Vonage Parameter Formatting Source: https://github.com/excid3/noticed/blob/main/docs/delivery_methods/vonage_sms.md Define a custom method to format the parameters sent to the Vonage API. The method should return a Hash containing the required parameters. ```ruby deliver_by :vonage, format: :format_for_vonage ``` ```ruby { api_key: vonage_credentials[:api_key], api_secret: vonage_credentials[:api_secret], from: notification.params[:from], text: notification.params[:body], to: notification.params[:to], type: "unicode" } ``` -------------------------------- ### Define New Comment Notifier with Multiple Delivery Methods Source: https://github.com/excid3/noticed/blob/main/README.md This notifier defines delivery via Action Cable for real-time UI updates, email for opted-in users, and a bulk notification to Discord. It also includes helper methods for generating messages and URLs. ```ruby # ~/app/notifiers/new_comment_notifier.rb class NewCommentNotifier < Noticed::Event deliver_by :action_cable do |config| config.channel = "NotificationsChannel" config.stream = :some_stream end deliver_by :email do |config| config.mailer = "CommentMailer" config.if = -> { !!recipient.preferences[:email] } end bulk_deliver_by :discord do |config| config.url = "https://discord.com/xyz/xyz/123" config.json = -> { { message: message, channel: :general } } end notification_methods do # I18n helpers def message t(".message") end # URL helpers are accessible in notifications # Don't forget to set your default_url_options so Rails knows how to generate urls def url user_post_path(recipient, params[:post]) end end end ``` -------------------------------- ### Define Notification Methods for Rendering Source: https://context7.com/excid3/noticed/llms.txt Defines helper methods within a notifier for rendering notification content in views. These methods, like `message`, `url`, and `icon`, are accessible on notification instances. ```ruby class InvoicePaidNotifier < ApplicationNotifier notification_methods do def message t(".message", amount: params[:amount]) end def url invoice_url(record) end def icon "💰" end end end ``` -------------------------------- ### Define Notification Helper Methods Source: https://github.com/excid3/noticed/blob/main/UPGRADE.md Wrap helper methods intended for use within notification views inside the `notification_methods` block. This makes I18n and URL helpers available. ```ruby class NewCommentNotifier < Noticed::Event deliver_by :email do |config| # ... end notification_methods do # I18n helpers still available here def message t(".message") end # URL helpers are available here too def url user_post_path(recipient, params[:post]) end end end ``` -------------------------------- ### Action Push Native Delivery Configuration Source: https://context7.com/excid3/noticed/llms.txt Configure the preferred delivery method for native push notifications on Apple and Android using the 'action_push_native' gem. This method allows for platform-specific formatting and data payloads. ```ruby class CommentNotifier < ApplicationNotifier deliver_by :action_push_native do |config| config.devices = -> { ApplicationPushDevice.where(owner: recipient) } config.format = -> { { title: "New comment from #{params[:commenter].name}", body: params[:comment].body.truncate(100), badge: 1 } } config.with_apple = -> { { category: "COMMENT_ACTION" } } config.with_google = -> { { android: { priority: "high" } } } config.with_data = -> { { post_id: record.id.to_s } } config.silent = false # config.class = "CustomPushNotification" # override ApplicationPushNotification end end ``` -------------------------------- ### Microsoft Teams Delivery Method Source: https://context7.com/excid3/noticed/llms.txt Posts an Adaptive Card or message to a Teams channel via incoming webhook. Requires `config.json` to define the message structure. ```ruby class DeploymentNotifier < ApplicationNotifier deliver_by :microsoft_teams do |config| config.url = Rails.application.credentials.dig(:microsoft_teams, :notification_url) config.json = -> { { "@type": "MessageCard", "@context": "https://schema.org/extensions", "summary": "Deployment complete", "themeColor": "0076D7", "sections": [{ "activityTitle": "🚀 Deployed #{params[:version]} to #{params[:environment]}", "activityText": "Deployed by #{params[:deployer].name} at #{Time.current.strftime("%H:%M")}" }] } } end end ``` -------------------------------- ### Querying JSON Parameters with SQLite Source: https://github.com/excid3/noticed/blob/main/UPGRADE.md Use this method to query JSON parameters when using SQLite. Ensure `param_name` is correctly defined and `Noticed::Coder.dump(self).to_json` is used for serialization. ```ruby model.where("json_extract(params, ?) = ?", "$.#{param_name}", Noticed::Coder.dump(self).to_json) ``` -------------------------------- ### Configure Discord Delivery Method Source: https://github.com/excid3/noticed/blob/main/docs/delivery_methods/discord.md Set up the Discord delivery method for a notification class. Specify the webhook URL and a JSON payload generator. This is useful for sending bulk notifications to a Discord channel. ```ruby class CommentNotification deliver_by :discord do |config| config.url = "https://discord.com..." config.json = -> { { # ... } } end end ``` -------------------------------- ### Slack Delivery Method Configuration Source: https://context7.com/excid3/noticed/llms.txt Configures the Slack delivery method to post messages via `chat.postMessage` or an incoming webhook URL. Requires `config.json` and optionally `config.url` and `config.headers`. ```ruby class AlertNotifier < ApplicationNotifier deliver_by :slack do |config| config.url = -> { recipient.slack_webhook_url } config.json = -> { { channel: recipient.slack_channel_id, text: "Alert: #{params[:message]}", blocks: [ { type: "section", text: { type: "mrkdwn", text: "*#{params[:title]}*\n#{params[:message]}" } } ] } } config.headers = -> { { "Authorization" => "Bearer #{Rails.application.credentials.slack.bot_token}" } } # config.raise_if_not_ok = false # suppress Slack {ok: false} errors end end ``` ```ruby AlertNotifier.with(title: "Disk Full", message: "Server disk usage exceeded 95%") .deliver(User.ops_team) ``` -------------------------------- ### Define a Notifier Class Source: https://github.com/excid3/noticed/blob/main/UPGRADE.md Use Noticed::Event as the parent class for your notifiers. This class tracks all Notifier deliveries and recipients. ```ruby class CommentNotifier < Noticed::Event end ``` -------------------------------- ### Configure Slack Bulk Delivery Source: https://github.com/excid3/noticed/blob/main/docs/bulk_delivery_methods/slack.md Configure the Slack delivery method with a webhook URL and a JSON payload generator. The `raise_if_not_ok` option can be set to `false` to disable checks for Slack's response. ```ruby class CommentNotification bulk_deliver_by :slack do |config| config.url = "https://slack.com..." config.json = -> { { # ... } } # Slack's chat.postMessage endpoint returns a 200 with {ok: true/false}. Disable this check by setting to false # config.raise_if_not_ok = true end end ``` -------------------------------- ### Discord Bulk Delivery Method Source: https://context7.com/excid3/noticed/llms.txt Posts a single message to a Discord channel via webhook. Requires `config.url` for the webhook and `config.json` for the embed structure. ```ruby class NewUserNotifier < ApplicationNotifier bulk_deliver_by :discord do |config| config.url = Rails.application.credentials.discord[:webhook_url] config.json = -> { { content: nil, embeds: [{ title: "New user signed up", description: "**#{params[:user].name}** (#{params[:user].email}) just joined!", color: 5763719, timestamp: Time.current.iso8601 }] } } end end NewUserNotifier.with(user: @user).deliver([]) # no individual recipients needed for bulk-only notifiers ``` -------------------------------- ### Gathering multiple iOS device tokens Source: https://github.com/excid3/noticed/blob/main/docs/delivery_methods/ios.md Configure the device_tokens to fetch all notification tokens for a recipient that are associated with the iOS platform. ```ruby deliver_by :ios do |config| config.device_tokens = -> { recipient.notification_tokens.where(platform: :iOS).pluck(:token) } end ``` -------------------------------- ### Configure iOS Delivery Method Source: https://github.com/excid3/noticed/blob/main/UPGRADE.md Configure the iOS delivery method with various options including APNS key, IDs, bundle identifier, and device tokens. Conditional delivery can be set using the `if` option. ```ruby class CommentNotifier < Noticed::Event include IosNotifier def data_only? false end def url comment_thread_path(record.thread) end end module IosNotifier extend ActiveSupport::Concern included do deliver_by :ios do |config| config.format = :ios_format config.apns_key = :ios_cert config.key_id = :ios_key_id config.team_id = :ios_team_id config.bundle_identifier = :ios_bundle_id config.device_tokens = :ios_device_tokens config.if = :send_ios_notification? end end def ios_format(apn) apn.alert = { title:, body: } unless data_only? apn.mutable_content = true apn.content_available = true apn.sound = "notification.m4r" apn.custom_payload = { url:, type: self.class.name, id: record.id, image_url: "" || image_url, params: params.to_json } end def ios_cert(*) Rails.application.credentials.dig(:ios, Rails.env.to_sym, :apns_token_cert) end def ios_key_id(*) Rails.application.credentials.dig(:ios, Rails.env.to_sym, :key_id) end def ios_team_id(*) Rails.application.credentials.dig(:ios, Rails.env.to_sym, :team_id) end def ios_bundle_id(*) Rails.application.credentials.dig(:ios, Rails.env.to_sym, :bundle_identifier) end def ios_device_tokens(notification) notification.recipient.ios_device_tokens end def send_ios_notification?(notification) recipient = notification.recipient return false unless recipient.is_a?(User) recipient.send_notifications? end end ``` -------------------------------- ### Define Notifier with Required Parameters Source: https://github.com/excid3/noticed/blob/main/README.md This notifier specifies required parameters `:branch` and `:record` using the `required_params` method. It includes a validation for the `:record` parameter and demonstrates how validation errors are raised if parameters are missing during delivery. ```ruby class CarSaleNotifier < Noticed::Event deliver_by :email { |c| c.mailer = "BranchMailer" } # `record` is the Car record, `Branch` is the dealership required_params :branch # To validate the `:record` param, add a validation since it is an association on the Noticed::Event validates :record, presence: true end ``` ```ruby CarSaleNotifier.with(record: Car.last).deliver(Branch.last) #=> Noticed::ValidationError("Param `branch` is required for CarSaleNotifier") CarSaleNotifier.with(record: Car.last, branch: Branch.last).deliver(Branch.hq) #=> OK ``` -------------------------------- ### Configure FCM Delivery Source: https://github.com/excid3/noticed/blob/main/docs/delivery_methods/fcm.md Set up the FCM delivery method within a notifier class, specifying credentials, device tokens, and notification JSON structure. ```ruby class CommentNotification deliver_by :fcm do |config| config.credentials = Rails.root.join("config/certs/fcm.json") config.device_tokens = -> { recipient.notification_tokens.where(platform: "fcm").pluck(:token) } config.json = ->(device_token) { { message: { token: device_token, notification: { title: "Test Title", body: "Test body" } } } } config.if = -> { recipient.android_notifications? } end end ``` -------------------------------- ### Email Delivery Method Configuration Source: https://context7.com/excid3/noticed/llms.txt Configures the Email delivery method using ActionMailer. Requires `config.mailer` and `config.method`. The mailer receives `notification`, `record`, and `recipient` merged into params. ```ruby class WelcomeNotifier < ApplicationNotifier deliver_by :email do |config| config.mailer = "UserMailer" config.method = :welcome config.if = -> { recipient.email_confirmed? } # config.args = -> { [extra_arg] } # positional args for the mailer method # config.kwargs = -> { { tier: "pro" } } # keyword args # config.enqueue = true # use deliver_later (rarely needed) end end ``` ```ruby class UserMailer < ApplicationMailer def welcome @notification = params[:notification] @user = params[:recipient] mail(to: @user.email, subject: "Welcome!") end end ``` ```ruby class UserMailerPreview < ActionMailer::Preview def welcome UserMailer.with(recipient: User.first).welcome end end ```