Skip to content

Commit

Permalink
(#13) generate slack channel for project
Browse files Browse the repository at this point in the history
  • Loading branch information
reabiliti committed Aug 5, 2018
1 parent 23b2938 commit 68dc937
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 0 deletions.
13 changes: 13 additions & 0 deletions app/jobs/projects/create_slack_channel_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

module Projects
# Runs create channel slack for project in asyncronous manner.
class CreateSlackChannelJob < ApplicationJob
queue_as :default

def perform(project_id)
project = Project.find(project_id)
Ops::Projects::GenerateProjectSlackChannel.call(project: project)
end
end
end
27 changes: 27 additions & 0 deletions app/operations/ops/projects/generate_project_slack_channel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

module Ops
module Projects
# This is the operation of creating a project channel to slack
class GenerateProjectSlackChannel < BaseOperation
step :create_slack_channel!
step :invite_members!

private

def create_slack_channel!(_ctx, project:, **)
SlackService.new(ENV['SLACK_TOKEN']).create_channel(project.slug)
end

def invite_members!(_ctx, project:, **)
members_slack_channel(project).each do |user|
SlackService.new(ENV['SLACK_TOKEN']).invite_to_channel(project.slug, user.email)
end
end

def members_slack_channel(project)
project.users + [project.author, User.joins(:roles).where(roles: { type: 'Roles::Mentor' }).sample]
end
end
end
end
6 changes: 6 additions & 0 deletions app/operations/ops/projects/kickoff.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class Kickoff < BaseOperation
step :activate_idea!
step :create_project!
step :add_users_to_project!
step :generate_project_slack_channel!

private

Expand All @@ -28,6 +29,11 @@ def add_users_to_project!(_ctx, idea:, **)
idea.project.users << vote.user
end
end

def generate_project_slack_channel!(_ctx, idea:, **)
::Projects::CreateSlackChannelJob.perform_later(idea.project.id)
true
end
end
end
end
7 changes: 7 additions & 0 deletions app/services/slack_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ def invite_to_channel(channel_name, email)
channel = channel_by_name(channel_name)
raise SlackIntegration::FailedApiCallException, "Channel with name '#{channel}' was not found" unless channel
client.conversations_invite(channel: channel['id'], users: user['id'])
rescue Slack::Web::Api::Errors::SlackError => e
handle_exception(e)
end

# For each new project we create a separate channel
Expand Down Expand Up @@ -60,4 +62,9 @@ def user_by_email(email)
def id_channels(channels)
channels.map { |channel| channel_by_name(channel)['id'] }.join(',')
end

def handle_exception(exception)
return true if exception.message == 'cant_invite_self'
raise
end
end
14 changes: 14 additions & 0 deletions spec/jobs/projects/create_slack_channel_job_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

require 'rails_helper'

describe Projects::CreateSlackChannelJob do
describe '#perform' do
let(:project) { create(:project) }

it 'calls Projects::Kickoff operation' do
expect(Ops::Projects::GenerateProjectSlackChannel).to receive(:call).with(project: project)
described_class.perform_now(project.id)
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# frozen_string_literal: true

require 'rails_helper'

describe Ops::Projects::GenerateProjectSlackChannel do
subject { described_class }
let!(:idea) { create(:idea, :with_project) }
let!(:service) { double }
let!(:user) { create(:user, :developer, :active) }
let!(:channel) { idea.project.slug }
before { create(:project_user, project: idea.project, user: user) }

describe '#call' do
before do
allow(SlackService).to receive(:new).with(any_args).and_return(service)
end
let!(:params) { { project: idea.project } }

context 'create Slack channel for project' do
it 'create channel' do
expect(service).to receive(:create_channel).with(idea.project.slug)
subject.call(params)
end
end

context 'user was not invited before' do
it 'invites member to Slack' do
allow(service).to receive(:create_channel).with(any_args)
expect(service).to receive(:invite_to_channel).with(channel, user.email)
subject.call(params)
end
end

context 'user was invited before' do
it 'handles exception properly' do
allow(service).to receive(:create_channel).with(any_args)
expect(service)
.to receive(:invite_to_channel)
.with(channel, user.email)
.and_raise(
Slack::Web::Api::Errors::SlackError,
'cant_invite_self'
)
subject.call(params)
end
end

context 'some other exception occured' do
it 'handles exception properly' do
allow(service).to receive(:create_channel).with(any_args)
allow(service)
.to receive(:invite_to_channel)
.with(channel, user.email)
.and_raise(
SlackIntegration::FailedApiCallException,
'some other message'
)
expect { subject.call(params) }
.to raise_error SlackIntegration::FailedApiCallException, 'some other message'
end
end
end
end
7 changes: 7 additions & 0 deletions spec/operations/ops/projects/kickoff_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

describe Ops::Projects::Kickoff do
subject { described_class }
let!(:service) { double }

describe '#call' do
before do
Expand All @@ -30,5 +31,11 @@
subject.call(params)
expect(idea.project.users.count).to eq 2
end

it 'run job to create slack channel' do
expect(::Projects::CreateSlackChannelJob)
.to receive(:perform_later)
subject.call(params)
end
end
end

0 comments on commit 68dc937

Please sign in to comment.