How to send slack notifications from Rails app using sidekiq
Tags: rails, sidekiq, slack
Published: 2023-02-06 05:00:00

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](https://github.com/mperham/sidekiq "Sidekiq gem docs") 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:

```ruby
gem 'sidekiq'
```

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

## Setting up Slack Notifier

The [`slack-notifier` ](https://github.com/slack-notifier/slack-notifier)gem is a client library for interacting with the Slack Web API. To install it, add it to your Gemfile:

```ruby
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](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:

```ruby
# 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-notifier](https://github.com/slack-notifier/slack-notifier)to 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.

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

![Slack Message Response 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n38aagicgvu18tzqcfs0.png)

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

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


![Slack Message Response 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8wbojtenaq3cklxhz9uh.png)
---- 
Happy Coding!
Contact me at [sulman@hey.com](mailto:sulman@hey.com)