How to publish Slack app using Rails
Tags: slack, ruby, rails
Published: 2019-11-13 08:42:42

---
title: How to publish Slack app using Rails
published: true
description: How to start off building a Slack app on Ruby on Rails and end up it has been in Slack App Directory.
tags: Slack, Ruby, RubyOnRails
---

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/z59ft589smq1jip765tc.png)

My friend nudged me to build [a Slack app](https://officedj.co) that shares what's currently playing on Spotify to Slack channel. For a couple of days, I have put the finishing touches on it from nothing.

This is my first time the Slack app built it done having in public although I had some for private workspace before. Only developing it is not enough you ought to submit it to Slack App Directory. Once passed it you would have completed done it.

I'm writing about how to start off building a Slack app on Ruby on Rails and end up it has been in Slack App Directory.

This slack app requires Slack and Spotify authentication and then notify the song information when users start playing on Spotify to the channel they set up on the app. It's simple. I don't write about how to use Spotify API here but they don't have webhook so I get this information once per 10 minutes.

## Let the building begin

1. Register Slack app
2. Develop Rails app
3. Submit the app
4. Let it list on Slack App Directory

### Register Slack app


Before building, you have to set up your own Slack workspace. I don't know so much about it but the app might be deleted at the same time the workspace has been deleted.

Go to [Slack API](https://api/slack.com) for registering the application. Only you have to set up is below.

* Take a note `Client ID` and `Client Secret` on App Credentials
* Add `redirect URL` to Permissions
* Add `channels:read` and `chat:write:bot` to scope on Permissions

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/w9bs6xd9pekllvbtjel8.png)

### Develop Rails app

#### Add an authentication

Build authentication with a famous gem `omniauth`. Installed it and then set up on `omniauth.rb`.

```ruby
gem 'omniauth'
gem 'omniauth-slack'
```

```ruby
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :slack,
    Rails.application.credentials[:slack][:consumer_id],
    Rails.application.credentials[:slack][:consumer_secret],
    scope: 'channels:read,chat:write:bot'
end
```

#### Add Session controller

Develop sessions that users can sign in with Slack and sign out it. You should prepare `sessions controller` and `user model`.

```
$ rails g controller sessions new destroy
$ rails g model Users name email provider uid token channel
```

Don't forget to add the column of uid, token, and channel for Slack authentication data here.

```ruby
class SessionsController < ApplicationController
  def create
    user = User.from_omniauth(request.env["omniauth.auth"])
    if user.save
      session[:user_id] = user.id
      redirect_to root_path
    else
      redirect_to root_path
    end
  end
 
  def destroy
    session[:user_id] = nil
    redirect_to root_path
  end
end  
```

```ruby
class User < ApplicationRecord
  def self.from_omniauth(auth)
    where(provider: auth.provider, uid: auth.uid).first_or_initialize.tap do |user|
      user.name = auth.info.name
      user.email = auth.info.email
      user.token = auth.credentials.token
      return user
    end
  end
end
```

```ruby
Rails.application.routes.draw do
  get 'auth/:provider/callback', to: 'sessions#create'
  get 'auth/failure', to: redirect('/')
  get 'signout', to: 'sessions#destroy', as: 'signout'
 
  resources :sessions, only: [:create, :destroy]
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
```

You can see the below screen on `/auth/slack`. And I wish you can create User data with Slack authentication.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/frm802sed15ztxks0fu3.png)

#### Install Slack Ruby Client

Recommend you to continue to develop with `slack-ruby-client`. It's a ruby and command-line client for the Slack Web, Real-Time Messaging and Event APIs.

```ruby
gem 'slack-ruby-client'
```

#### Create Slack Ruby Client

Create the model that gets some through Slack API.

```ruby
class Manager::SlackApiClient
    attr_reader :client, :slack_user
  
    def initialize(slack_user)
      @slack_user = slack_user
      @client = Slack::Web::Client.new(token: slack_user.token)
      @client.auth_test
    rescue => e
      Rails.logger.warn(<<~LOG)
        Error @Manager::SlackApiClient#initialize
        Msg: #{e.class} #{e.message}
      LOG
  
      @client = nil
    end
  
    def valid?
      client
    end
  end
end
```

#### Get channels info 

The app should allow users to choose a channel that they get notified.

```ruby
 def channels
   client.channels_list.channels
 end
```

```ruby
class SettingsController < ApplicationController
  def index
    @user = current_user
    client_manager = Manager::SlackApiClient.new(@user)
    if client_manager.valid?
      @slack_channels = client_manager.channels
    else
      flash[:danger] = 'Slack token expired. Please link Slack app again.'
    end
  end
end
```

#### Send notifications when playing

The app should send notifications when users start playing on Spotify. This requires information like song name, URL, artist name and album name.

```ruby
slack_client_manager = Manager::SlackApiClient.new(user)
slack_client_manager.post_song_message(@current_playing) if slack_client_manager.valid?
```

```ruby
  def post_song_message(song)
    attachments = {
      text: "🎧 #{song.user.name} is currently playing #{song.name}",
      "fields": [
        {
          "title": "Artist",
          "value": song.artist,
          "short": true
        },
        {
          "title": "Album",
          "value": song.album,
          "short": true
        },
        {
          "title": "Spotify url",
          "value": song.url,
          "short": false
        }             
      ],      
      color: "#f9da00"
    }
    client.chat_postMessage(channel: "##{slack_user.channel}", attachments: [attachments])
  end
```

You can arrange what kind of notification content you send. Only text is easy to build it and you can add some features when you build with `attachments`. Please check it [here](https://api.slack.com/docs/message-attachments).

Okay, That's all. All you have to do left to submit the app to Slack App Directory.

### Submit the app

You don't have to submit the app as long as your app is used on your workspace. But Slack requires some tests and reviews before you have it for the public.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/mssrbm8yugv40hh9jsg6.png)

Go to `Manage distribution`. You have to agree with some terms and check if the app works under the configuration Sack defines. If your app requires the other party, you supposed to write about its authentication information.


It takes you a few days to pass the review. In my experience, this review is not easy. They're careful that the app would work well.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/tpiyj9fbc0f2ufsl5c8s.png)


#### Let it list on Slack App Directory

Done. You would be glad if the app you built listed on Slack App Directory.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/ex2ag5ij4sf9a5ws27hq.png)