Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

分報チャンネルがアカウントIDの頭文字のグループ内で自動作成されるようにする #6522

Conversation

ymmtd0x0b
Copy link
Contributor

@ymmtd0x0b ymmtd0x0b commented May 15, 2023

Issue

概要

入会時に自動作成される分報チャンネルのグループを『 固定の分報グループ ( 新規🎉(ひとりごと・分報) ) 』から『 アカウントIDの頭文字に合致する分報グループ ( 数字・A・B・C (ひとりごと・分報) 等 ) 』に変更しました

変更確認方法

※変更を確認するためには、事前に確認用のDiscordサーバーを作成しDiscordサーバーのID/デフォルトグループのID/認証用のBotトークンを環境変数に設定する必要があります

事前準備

準備手順

  1. Discordサーバーの作成
    #5454 の『Discordへの通知を確認するための準備』の手順に従い確認用のDiscordサーバーを作成して下さい ( ※WebhookURLの取得は不要です )

  2. DiscordサーバーのIDを取得する
    #6185 の『Discord サーバーのIDを取得する』の手順に従いDiscordサーバーのIDを控えて下さい

  3. デフォルトグループのIDを取得する
    3-1. 確認用のDiscordサーバーでデフォルトグループを作成します ( 例: 新規🎉(ひとりごと・分報) )
    3-2. #6185 の『分報チャンネルのカテゴリーのIDを取得する』の手順に従ってDiscordサーバーのIDを控えて下さい

  4. 認証用のBotトークンを追加する
    #6185 の『Discord Bot のトークン情報を取得する』の手順に従い、Botの作成・確認用のDiscordサーバーへ追加を行った後にBotトークンを控えて下さい

  5. 環境変数にDiscordサーバーのID/デフォルトグループのID/認証用のBotトークンを設定する
    手順2~3で控えた情報を#6185 の『 注意・伝達事項 』に記載されている手順に従い環境変数へ設定して下さい

準備後の状態

ここまでの作業の結果をご参考までに例示します

Discord画面 .profileの内容
confirm_discord env

確認手順

  1. 確認用のDiscordサーバーに新たに数字・A・B・C (ひとりごと・分報)の名前でグループ (カテゴリー)を作成する
  2. feature/change-the-category-of-the-discord-channel-that-is-automatically-created-when-you-joinをローカルに取り込む
  3. bin/rails sでサーバーを立ち上げる
  4. http://localhost:3000 にアクセスして未ログインであることを確認
  5. http://localhost:3000/users/new にアクセスして現役生 ( アカウント名:alice ) として参加登録を行う
    • アカウント名以外の項目の内容はこのPRの機能に影響しないので何でもOKです
    • クレジットカードの番号は Test cards | Stripe のドキュメント を参照して下さい
  6. http://localhost:3000/users/new にアクセスして現役生 ( アカウント名:zoe ) として参加登録を行う
  7. 確認用のDiscordサーバーを起動し、数字・A・B・C (ひとりごと・分報)グループalice新規🎉(ひとりごと・分報)zoe の分報チャンネルがそれぞれ作成されている事を確認する

Screenshot

変更前

discord_textchannel_before

変更後

discord_textchannel_after

補足情報

以下に動作確認やレビューに役立つと思われる情報を記載します

Discord Web API におけるチャンネルについて

以下に挙げた機能は全て Discord Web API 上で『チャンネル』として扱われます

種類 内容 このPRにおける役割
テキストチャンネル テキストメッセージや画像を投稿、共有できるチャンネル 分報チャンネル
ボイスチャンネル 音声やビデオ通話、画面共有ができるチャンネル このPRでは使用しない
カテゴリ チャンネルをグループとして内包するチャンネル グループ

※このPRにおけるグループとカテゴリは同義です


アカウントIDに使用可能な文字と使用ルール

以下に示すルールが現時点におけるアカウントIDに使用可能な文字になります

  • 文字数は最小で3文字以上が必要
  • 半角英数字と-(ハイフン)のみが使用可能
  • 先頭と最後にハイフンの使用できない
  • ハイフンは連続で使用できない

グループ分類の規則

アカウントIDの頭文字によって分類するグループの規則は以下のようになります

頭文字のパターン 分類グループ
a~z チャンネル名に各英字の大文字を含むグループ 数字・A・B・C (ひとりごと・分報)
M (ひとりごと・分報)
0~9 チャンネル名に"数字"という文字列を含むグループ 数字・A・B・C (ひとりごと・分報)
半角英数字以外※1 デフォルトグループ※2 新規🎉(ひとりごと・分報)

※1

将来的な仕様変更が発生した場合でも想定内の問題として対応・異常の発見ができるように、アカウントIDの頭文字が半角英数字以外でも『デフォルトグループ』に分類されるよう対策しています ( 質問・雑談チャンネルにて了承を頂きました )

※2

現在の仕様ではFBCのDiscordサーバーにある新規🎉(ひとりごと・分報)のチャンネルIDを環境変数経由で取得し、新規ユーザーの分報チャンネルのグループとして設定されています。このPRのマージ後はチャンネル名を変更し、適切な分類ができない場合に対処するためのグループとして再利用します ( 質問・雑談チャンネルにて了承を頂きました )

また、アカウントIDの頭文字が半角英数字だったとしても適切なグループに分類できない場合は『デフォルトグループ』へ分類されるように設定しています

例えば、何らかの要因でAの文字を含むグループが存在しない場合、アカウントIDの頭文字が a から始まるユーザーの分報チャンネルはデフォルトグループに作成されます


その他

もし、より詳しい情報が必要な場合は以下のリンクが参考になると思いますので、参照して頂ければと思います

@ymmtd0x0b ymmtd0x0b force-pushed the feature/change-the-category-of-the-discord-channel-that-is-automatically-created-when-you-join branch from 8f74196 to 4d7a38f Compare May 15, 2023 03:20
@ymmtd0x0b ymmtd0x0b marked this pull request as ready for review May 29, 2023 02:06
@ymmtd0x0b
Copy link
Contributor Author

@syo-tokeshi
お疲れ様です!
こちらのレビューをお願いしたいのですが、ご都合いかがでしょうか?🙏

@toke04
Copy link
Contributor

toke04 commented Jun 6, 2023

@ymmtd0x0b
はい!やらせて下さい🙇‍♂️

よろしくお願いいたしますー😊

早ければ土曜日までにレビューします🙇‍♂️(なかなかタフそうですね、、一緒に勉強させて下さい!!)

@toke04
Copy link
Contributor

toke04 commented Jun 6, 2023

@ymmtd0x0b
お疲れ様です。
手順書に従って、通知チャネルを作ったつもりですが、ディスコードに、ユーザーが追加されない感じです。
スクリーンショット 2023-06-06 23 58 50

上の写真の
「新規🎉(ひとりごと・分報)」のチャネルは、
「チャネルを作成」から作っておりますでしょうか?
スクリーンショット 2023-06-07 0 00 43

botもディスコードに参加しております
スクリーンショット 2023-06-07 0 03 15

スクリーンショット 2023-06-07 0 03 49

「ピコっ」という音が鳴り、反応している気はするのですが、何か解決するヒント等、持ち合わせてないでしょうか?

@toke04
Copy link
Contributor

toke04 commented Jun 6, 2023

名前はBootcamp2としてますが、設定自体は上手くいってると思うんですよね、、
スクリーンショット 2023-06-07 0 31 55

スクリーンショット 2023-06-07 0 32 06

@ymmtd0x0b
Copy link
Contributor Author

@syo-tokeshi
ご連絡ありがとうございます!私の方でも調査してみます!

@toke04
Copy link
Contributor

toke04 commented Jun 6, 2023

あ、ちょっと解決しそうです🙇‍♂️

カテゴリーを作成からグループを作るのですね
スクリーンショット 2023-06-07 0 40 24

カテゴリーを作成からグループを作り直しました🙇‍♂️
スクリーンショット 2023-06-07 0 41 06

@toke04
Copy link
Contributor

toke04 commented Jun 6, 2023

@ymmtd0x0b
大変失礼しました🙇‍♂️

解決しました
スクリーンショット 2023-06-07 0 46 57
スクリーンショット 2023-06-07 0 47 05

@ymmtd0x0b
Copy link
Contributor Author

ymmtd0x0b commented Jun 6, 2023

@syo-tokeshi
多分、その部分の可能性が高そうです!

[追記]
解決したみたいで良かったです!他にも上手く行かない箇所があればご連絡下さい!

@toke04
Copy link
Contributor

toke04 commented Jun 6, 2023

@ymmtd0x0b
はい!
無事解決しました😊

これで安心してコードレビューに取り掛かれそうです😆(明日以降になります🙇‍♂️)

夜遅くにすみませんでした!🙇‍♂️

解決したみたいで良かったです!他にも上手く行かない箇所があればご連絡下さい!

かしこまりました!!🙇‍♂️

@ymmtd0x0b ymmtd0x0b requested a review from toke04 June 7, 2023 08:10
@ymmtd0x0b
Copy link
Contributor Author

@syo-tokeshi
すみません!レビューワーへの追加を忘れていたので、只今実行しました🙏


bot = Discordrb::Bot.new(token: token, log_mode: :silent)
channels_data.map { |channel_data| Discordrb::Channel.new(channel_data, bot) }
rescue Discordrb::Errors::CodeError => e
Copy link
Contributor

@toke04 toke04 Jun 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[自分用補足]
こちらのrescue の使い方は「rescue修飾子」と言い、
https://docs.ruby-lang.org/ja/latest/doc/spec=2fcontrol.html

このようなコードがあった場合
式1 rescue 式2
式1で例外が発生したら、式2を評価する
スクリーンショット 2023-06-07 19 48 38

module Discord
class TimesCategory
include ActiveSupport::Configurable
config_accessor :default_times_category_id, instance_accessor: false
Copy link
Contributor

@toke04 toke04 Jun 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[自分用補足]
config_accessor は、

  • クラス
  • インスタンス

両方から属性に対して

  • getter
  • setter

の両方の操作が出来る
https://api.rubyonrails.org/classes/ActiveSupport/Configurable/ClassMethods.html

VCR.use_cassette 'discord/server/channels' do
actual = Discord::Server.channels(id: '1234567890123456789', token: 'Bot valid token')
assert_kind_of Array, actual
assert actual.all?(Discordrb::Channel)
Copy link
Contributor

@toke04 toke04 Jun 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[自分用補足]
all?メソッドは、引数を渡した場合、パターンに全てマッチしていたら真を返すので、
Discordrb::Channelクラスのインスタンスであるか確認している
https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/all=3f.html

module Discordrb
  class Channel

Rails.logger.stub(:error, ->(message) { logs << message }) do
VCR.use_cassette 'discord/server/channels' do
actual = Discord::Server.channels(id: '1234567890123456789', token: 'Bot valid token')
assert_kind_of Array, actual
Copy link
Contributor

@toke04 toke04 Jun 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[自分用補足]
こちらでは、actual が配列で取れている事を確認。
下のall?メソッドで一つ一つの確認をしている。


Discord::Server.stub(:enabled?, -> { false }) do
actual = Discord::Server.channels(id: '1234567890123456789', token: 'Bot valid token')
assert_nil actual
Copy link
Contributor

@toke04 toke04 Jun 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[質問]
こちら、

  • サーバーが認証で失敗している(guild_id && authorize_tokenこちらのどれかで失敗している)ので、チャネルの取得が上手くいかない

なので、

  • actualがnilである
  • エラーログも格納されない

という理解でよろしいでしょうか?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@syo-tokeshi
はい!おおよそその通りです!

少し補足いたしますと

  • 環境変数に設定しているはずのDiscordサーバー情報である "guild_id" と "authorize_token" のどちらかが nil の場合は『サーバーへのアクセス自体を実行しない』

ので

  • actualがnilである
  • エラーログも格納されない

になります!

Copy link
Contributor

@toke04 toke04 Jun 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ご質問に親切に答えてくださってありがとうございます🙇‍♂️
補足説明助かります🙇‍♂️(理解しました!)

明日の夜までに返信出来る事を目安に頑張ります😄
本日少しバタバタしておりました🙇‍♂️

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@syo-tokeshi
明日の夜まででなくても全然大丈夫です〜👍️
tokeさんのご都合や体調を優先して下さい!


test '.categorize_by_initials_with_not_matched_category' do
Discord::Server.stub(:categories, @stub_times_categories) do
actual = Discord::TimesCategory.categorize_by_initials('ありす🔰')
Copy link
Contributor

@toke04 toke04 Jun 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[質問]
すみません、念のため確認なのですが、サインアップ(新規会員登録)時に使用される事は想定しないで、単純に「モデルのメソッドのテスト」という事で追加した、という認識でよろしいでしょうか?
スクリーンショット 2023-06-09 8 50 35

なぜそのような事を言うのかと言いますと、
サインアップ(新規会員登録)からアカウント名を「ありす🔰」では登録出来ないと思うからです。
下に確認のためサインアップ(新規会員登録)のフローを書きます🙇‍♂️

サインアップ(新規会員登録)の処理フロー

前提

  1. Discordへ登録される名前は、login_nameがそのまま登録される。
  2. アカウント登録時は、以下の制限がある。
  • 文字数は3文字以上が必要です。
  • 半角英数字と-(ハイフン)のみが使用できます。
  • 先頭と最後にハイフンを使用することはできません。
  • ハイフンを連続して使用することはできません。
スクリーンショット 2023-06-09 7 59 05

処理の確認

  1. ユーザー作成時に、こちらの処理が走る(新規作成した@userを次に渡す)

    Newspaper.publish(:student_or_trainee_create, @user) if @user.student?

  2. こちらの処理で、受け取った@user(サインアップしたユーザー)を、TimesChannelCreatorクラスのインスタンスとして次に渡す

    Newspaper.subscribe(:student_or_trainee_create, TimesChannelCreator.new)

  3. ユーザーのlogin_nameの値で、ディスコードのチャネルを作成する

    class TimesChannelCreator
    def call(user)
    raise ArgumentError, "#{user.login_name}は現役生または研修生ではありません。" unless user.student_or_trainee?
    times_channel = Discord::TimesChannel.new(user.login_name)
    if times_channel.save
    user.update(times_id: times_channel.id)
    else
    Rails.logger.warn "[Discord API] #{user.login_name}の分報チャンネルが作成できませんでした。"
    end
    end
    end

念のため、saveメソッドまでここに書いておきます(ここで、login_nameをそのままディスコードのチャネル名に使っている感じですよね🙇‍♂️)

module Discord
  class TimesChannel
    class << self
      def to_channel_name(username)
        username.downcase
      end
    end

    def initialize(username)
      @name = Discord::TimesChannel.to_channel_name(username)
    end

    def save
      @channel = Discord::Server.create_text_channel(
        name: @name,
        parent: Discord::TimesCategory.categorize_by_initials(@name)
      )
スクリーンショット 2023-06-09 8 47 43

Copy link
Contributor

@toke04 toke04 Jun 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

長くなりましたが、ようは
Discord::TimesCategory.categorize_by_initials('ありす🔰')

  • このメソッドが、引数としてありす🔰のような値が渡ってきて呼び出されるケースは現状ではないが、メソッドとして、もしこのような値が渡ってきた場合を想定してテストを記述している

という理解でよろしいでしょうか?

[私の考え]
今現在使われるケースを想定したテストを書いた方が良いと思いますので、
こちらにマッチする引数を渡した方が良い気がしました🙇‍♂️
スクリーンショット 2023-06-09 9 02 19
[例] ※日本人&韓国人のユーザーさんがFBCに加入してくる事を想定してこの名前にしました🙇‍♂️(日本人の名前は特に使った方が良いような気がします(大多数なので))

  • sato777
  • kim7777

等です🙇‍♂️

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ymmtd0x0b
お疲れ様です。
後から考えてみたのですが、

  • モデルのテスト = 単体テスト

とは、他のクラスの事は考慮せず、それ単体(今回で言うとDiscord::TimesCategoryクラス)の機能をテストする、という観点で言うと、ヤマモトさんの今のままのテストコードで良い気がしてきました🙇‍♂️
https://and-engineer.com/articles/X_-EBRAAACcAJnau

つまり、私が最初に言ってた「usersコントローラーから呼ばれてますよね」みたいな理屈は関係なく、
あくまでDiscord::TimesCategoryクラスのメソッドをテストすれば良いと思うので、このままで良さそうです(今のテストで十分、メソッドのテストが出来ていると思います)🙇‍♂️

参考文献

https://and-engineer.com/articles/X_-EBRAAACcAJnau

単体テストは、UT工程とも呼ばれ、「Unit Test」の通り、メソッドや関数などの1つ1つの小さな単位ごとに行うテストのことです。
1つの画面であったり、1つの機能であったりで実施される動作をテストすることが目的となっています。
しかし、実際にシステム開発で作るプログラムでは、画面や機能が複数存在している場合が多いです。
動作の連携に関しては単体テストでは実施しません。
後で紹介する結合テストで行うテストとなります。
スクリーンショット 2023-06-11 10 42 08

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

はい!このコードではDiscrodカテゴリーの分類パターンをテストしたいだけなので、ユーザー名に特に意味はないと捉えています!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

了解です!🙇‍♂️
「単体テスト」の観点から、自分もそのままで良いと思います🙇‍♂️


test '.categorize_by_initials_with_invalid_name' do
Discord::Server.stub(:categories, @stub_times_categories) do
actual = Discord::TimesCategory.categorize_by_initials(nil)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

こちらはそのままで良いと思います🙇‍♂️

@toke04
Copy link
Contributor

toke04 commented Jun 9, 2023

@ymmtd0x0b
お疲れ様です🙇‍♂️
レビュー完了しました🙇‍♂️

私自身もの凄く学ばせて頂きました😄
本issueかなり難しかったと思うので、ここまで実装できた事にめちゃくちゃリスペクトしちゃいました😊

クラス設計とかもめちゃくちゃ良いと思いました😊


私が今回話し合いたいのはこちら2点だけになります
#6522 (comment)
#6522 (comment)

変更した方が良いかもしれないと思ったのはこの二箇所のみです(引数のみ)

actual = Discord::TimesCategory.categorize_by_initials('alice🔰')

actual = Discord::TimesCategory.categorize_by_initials('ありす🔰')


実装自体も、本番にマージしても問題は起きないと思いました🙇‍♂️

[私の検証証跡]
スクリーンショット 2023-06-09 9 37 43
本番にマージされたら、自動でこういうカテゴリーに入って便利ですね😊
スクリーンショット 2023-06-09 9 38 12

@toke04
Copy link
Contributor

toke04 commented Jun 11, 2023

@ymmtd0x0b
お疲れ様です。

結論から言うと、「今回のヤマモトさんのコードに修正が必要な箇所はなさそう」というのが私の結論です🙇‍♂️
「単体テスト」の概念を見直すと、このままで良いと思ったからです🙇‍♂️

最初は「変更が必要そう」と発言して、失礼しました🙇‍♂️

Copy link
Contributor

@toke04 toke04 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

変更して欲しい箇所がございませんので、Approveさせて頂きます🙇‍♂️
勉強させていただきました!!😄

@ymmtd0x0b
Copy link
Contributor Author

@syo-tokeshi
こちらこそ、丁寧に確認して頂きありがとうございます🙏

テスト名に使用するユーザー名は現状の仕様に合わせることも可能ですが、Approve して頂いた後に変更すると少しややこしくなりそうなので、今回はこのまま行こうと思います!

@toke04
Copy link
Contributor

toke04 commented Jun 11, 2023

@syo-tokeshi こちらこそ、丁寧に確認して頂きありがとうございます🙏

@ymmtd0x0b
ありがとうございます😊
めっちゃ勉強になりました!😄

  • Discord連携のロジック
  • VCR
  • スタブ

等、めっちゃ勉強になりました!

テスト名に使用するユーザー名は現状の仕様に合わせることも可能ですが、Approve して頂いた後に変更すると少しややこしくなりそうなので、今回はこのまま行こうと思います!

はい!それで良いと思います😆
Approveしましたー!🙇‍♂️

@ymmtd0x0b ymmtd0x0b requested a review from komagata June 11, 2023 15:33
@ymmtd0x0b ymmtd0x0b force-pushed the feature/change-the-category-of-the-discord-channel-that-is-automatically-created-when-you-join branch from 4d7a38f to 9623033 Compare June 11, 2023 15:41
@ymmtd0x0b
Copy link
Contributor Author

@komagata
お疲れ様です!
メンバーから Approve 頂きましたので、レビューをお願い致します🙇‍♂️

Copy link
Member

@komagata komagata left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

確認させて頂きました。OKです〜🙆‍♂️

@komagata komagata merged commit 5b808e3 into main Jun 20, 2023
@komagata komagata deleted the feature/change-the-category-of-the-discord-channel-that-is-automatically-created-when-you-join branch June 20, 2023 15:06
@github-actions github-actions bot mentioned this pull request Jun 20, 2023
13 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants