Ruby on RailsでSlack APIを使って通知機能を実装する手順

# Ruby on Rails で Slack API を使って通知機能を実装する手順

## はじめに

アプリ開発において、エラー発生時にすぐに通知を受け取れるようにすることは非常に重要です。Slack は多くの開発チームが利用している報連相ツールであり、Ruby on Rails から Slack へ通知を送る機能を実装することで、早く問題やエラーなどを発見して対応することが可能です。

この記事では、その方法について解説します。

## Slack アプリの作成

今回は社内の既存のワークスペースに通知したいので、このステップはスキップします。もし新規の場合は、まずは通知したい Slack のワークスペースとチャンネルを作成しておきましょう。

### Slack アプリの作成と Webhook URL の取得

1. 下記の URL にアクセスして、右の「Create New App」ボタンを押してください。
   https://api.slack.com/apps
   ![スクリーンショット 2025-04-17 14.10.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827838/f53773a8-c434-46a8-87b3-85bd2c40eaad.png)

2. 「From scratch」ボタンを押して、次の入力画面に進みます。
   ![スクリーンショット 2025-04-17 14.12.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827838/ba695fb5-d663-438c-8434-ca16a3e3c45d.png)

3. アプリ名とワークスペースを記入して「Create App」ボタンを押してください。
   ![スクリーンショット 2025-04-17 14.13.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827838/94d46c3c-61f0-4dc5-9eae-da91658ea9fe.png)


4. アプリとして投稿することのできる投稿先チャンネルを指定してください。
   ![スクリーンショット 2025-04-17 14.52.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827838/aacb3bd9-fca9-4a04-b069-6ae62c518588.png)

5. 作成したアプリの詳細画面で「Incoming Webhooks」をクリックして、「Activate Incoming Webhooks」をオンにします。
   ![スクリーンショット 2025-04-17 14.19.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827838/43e2a22f-364d-4ae9-a48f-f9ab2b6e7fff.png)

6. 同じページの一番下にスクロールして、「Webhook URL」をコピーしてRailsアプリの`.env`ファイルに環境変数として設定してください。

```env
# .env
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/.../.../...
```

   ![スクリーンショット 2025-04-17 14.21.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827838/d4d7db84-067d-4267-a3ff-51524806c432.png)



## Rails アプリでの実装

### Gem のインストール

まず、Gemfile に `slack-notifier` を追加します。

```ruby
# Gemfile
gem "slack-notifier"
```

その後、bundle install を実行してください。

```bash
bundle install
```

### 通知用のモデル作成

下記の SlackNotifier クラスを作成します。必要に応じてコードを調整してください。

```ruby
# app/models/slack_notifier.rb
class SlackNotifier
  attr_reader :client
  
  def initialize
    @client = Slack::Notifier.new(ENV['SLACK_WEBHOOK_URL'])
  end
  
  def self.slack(message)
    @slack ||= new
    @slack.send(message)
    Rails.logger.info message
  end
  
  def self.slack_with_mention(message)
    @slack ||= new
    @slack.send_with_mention(message)
    Rails.logger.error message
  end
  
  def send(message)
    client.ping(message)
  rescue Slack::Notifier::APIError => e
    Rails.logger.error('APIError')
    Rails.logger.error(e.message)
  rescue => e
    Rails.logger.error('SlackNotifierError')
    Rails.logger.error(e.message)
  end
  
  def mention(message)
    "<!channel>\n#{message}"
  end
  
  def send_with_mention(message)
    send(mention(message))
  end
end
```

### エラーハンドリングの実装

ご参考までに、必要に応じてコードを調整してください。

```ruby
# app/controllers/application_controller.rb
class ApplicationController < ActionController::API
  include DeviseTokenAuth::Concerns::SetUserByToken
  rescue_from ActiveRecord::RecordNotFound, with: :record_not_found
  rescue_from ActiveRecord::RecordInvalid, with: :record_invalid
  rescue_from StandardError, with: :handle_standard_error
  
  private
  
  def record_not_found(exception)
    SlackNotifier.slack_with_mention(exception.message)
    render json: { message: "レコードが見つかりません" }, status: :not_found
  end
  
  def record_invalid(exception)
    SlackNotifier.slack_with_mention(exception.message)
    render json: { message: exception.message }, status: :unprocessable_entity
  end
  
  def handle_standard_error(exception)
    log_and_notify_error("Standard error", exception)
    render json: { message: "Internal Server Error: #{exception.message}" }, status: :internal_server_error
  end
  
  def log_and_notify_error(error_type, exception)          
    error_message = [
      "#{error_type}が発生しました:",
      "エラーメッセージ: #{exception.message}",
      "バックトレース:",
      exception.backtrace&.first(3)&.join("\n")
    ].join("\n")
    SlackNotifier.slack_with_mention(error_message)
  end
end
```

## 動作確認

そのために、以下のコードをコンソールに実行して、テストできます。

```ruby
# コンソールを開く
rails c

# 環境変数のセットアップ確認
puts "SLACK_WEBHOOK_URL: #{ENV['SLACK_WEBHOOK_URL'].present? ? '設定済み' : '未設定'}"

# 通常メッセージの送信テスト
SlackNotifier.slack("これはテストメッセージです。")

# メンション付きメッセージの送信テスト
SlackNotifier.slack_with_mention("これは@channelメンションつけのテストメッセージです。")

# エラー発生時のテスト (例: 存在しないレコードを検索)
begin
  User.find(-1)  # 存在しないIDを指定
rescue => e
  SlackNotifier.slack_with_mention("(テスト)エラーが発生しました: #{e.message}")
end
```

アプリを実行してテストし、Slack チャンネルにメッセージが届くかどうかを確認しましょう。