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:
- go to https://slack.com/apps/A0F7XDUAZ-incoming-webhooks
- choose your team, press configure
- in configurations, press add configuration
- 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:
-
message
(text) (required) -
status
(text -> one of'good', 'warning', 'danger'
) (optional) (default -> ‘good’) -
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
Top comments (0)