How to send slack notifications from Rails app using sidekiq

Learn how to send Slack notifications from your Rails app using sidekiq and slack-notifier gems. This blog post covers the installation and setup of the gems, setting up a Slack App, adding a webhook URL, creating a SlackMessage library, and using it to send messages.

How to send slack notifications from Rails app using sidekiq
How to send slack notifications from Rails app using sidekiq

It can be helpful in a Rails application to send notifications to a Slack channel, for example, when a new user signs up, or an important task has been completed. This blog post will look at how to use the sidekiq and slack-notifier gems to set up Slack notifications for your Rails application.

Installing Sidekiq

Sidekiq is a background job processor for Ruby applications, which is useful for running time-consuming tasks without blocking the main thread. To install Sidekiq, add it to your Gemfile:

gem 'sidekiq'

Run bundle install. Use the docs available at https://github.com/mperham/sidekiq for more config of the sidekiq.

Setting up Slack Notifier

The slack-notifier gem is a client library for interacting with the Slack Web API. To install it, add it to your Gemfile:

gem 'slack-notifier'

Then, run bundle install to install the gem. Once the gem is installed, you'll need to add a Slack App to get a webhook URL that tells where to send the message.

Adding the Webhook URL:

To get the WEBHOOK_URL, you need:

  1. go to https://slack.com/apps/A0F7XDUAZ-incoming-webhooks
  2. choose your team, press configure
  3. in configurations, press add configuration
  4. choose a channel, and press "Add Incoming WebHooks integration"

Now you are ready to send notifications to your slack workspace through this webhook URL.

Save this webhook URL in your credentials in rails using rails credentials:edit with identifier: slack_webhook_url so that we can use this in the future in our code.

SlackMessage lib

Now in the lib directory, create a new file named slack_message.rb and add the following contents:

# lib/slack_message.rb
require 'slack-notifier'
# Sends message to Slack
class SlackMessage
  include Sidekiq::Worker
  sidekiq_options queue: 'default', retry: 1

  DEFAULT_CHANNEL = if Rails.env.production?
                      '#webhook-production'
                    else
                      '#webhook-staging'
                    end

  # args = JSON string
  # {
  #   message: Text Message
  #   status: good, warning, danger
  #   channel: #channel
  # }
  # sends message to slack
  # example:
  # SlackMessage.perform_async({ message: 'Hello World', status: 'good' }.to_json)
  def perform(args)
    Rails.logger.info "'SlackMessage' with args: #{args}"
    args = JSON.parse(args).with_indifferent_access

    channel = args[:channel] || DEFAULT_CHANNEL
    color = color(args[:status] || 'good')
    note = note(args[:message] || nil, color)

    # Send message to slack
    ::Slack::Notifier.new(Rails.application.credentials.slack_webhook_url)
                     .post channel: channel,
                           attachments: (note ? [note] : nil)
  end

  # message = Text Message
  # color = #hex
  # returns hash supported by slack-notifier
  def note(message, color)
    {
      fallback: message,
      text: message,
      color:
    }
  end

  # status = good, warning, danger
  # returns #hex color according to status
  def color(status)
    case status.to_sym
    when :warning
      '#ffff00'
    when :danger
      '#ff0000'
    else
      '#00ff00'
    end
  end
end

This code is a Ruby class that sends messages to Slack. It takes a JSON string as an argument, which contains the message, status (good, warning, danger), and channel. The class then parses the JSON string and sets the channel, color (based on status), and note (message and color). Finally, it sends a message to Slack using the Slack Notifier API.

Here I have made this library to make slack notifier easy with fewer configurable options. You can see the docs at https://github.com/slack-notifier/slack-notifierto see more options this gem provides.

This lib needs 3 inputs:

  1. message (text) (required)
  2. status (text -> one of 'good', 'warning', 'danger') (optional) (default -> ‘good’)
  3. channel (text) (optional) (default -> ‘webhook-staging’)

Call where needed

To send a message anywhere in code, write a one-liner, and by the use of sidekiq, the message will be sent to asked slack channel in the background without waiting to be executed.

For example, I add the after_create callback of the user in the code. This will tell me when a new user signs up on my platform.

SlackMessage.perform_async({ message: "New User: #{name} (#{email}) with id: #{id}", status: 'good', channel: '#new-users' }.to_json) 

Also, when the user is removed or deletes itself, in the before_destroy callback:

SlackMessage.perform_async({ message: "User Removed: #{name} (#{email}) with id: #{id}", status: 'danger', channel: '#removed-users' }.to_json) 

Happy Coding!

Contact me at sulman@hey.com