グループと信頼レベルの組み合わせによるタイトル自動化のベストプラクティス

こんにちは。

グループメンバーシップと信頼レベルの組み合わせに基づいて、ユーザータイトルを自動的に割り当てる最善の方法を探しています。たとえば、次のようになります。

  • ユーザーがグループ A に属し、信頼レベルが 1 の場合、タイトルは「A TL1」になります。
  • ユーザーがグループ A に属し、信頼レベルが 2 の場合、タイトルは「A TL2」になります。
  • ユーザーがグループ B に属し、信頼レベルが 1 の場合、タイトルは「B TL1」になります。
  • …など

これまでに調べたところ、主な方法は次のとおりです。

  1. Dynamic Groups プラグインを使用して、各グループと信頼レベルの組み合わせごとに個別のグループを作成します(例: a-tl1a-tl2b-tl1 など)。
  2. これらの各グループにデフォルトのタイトルを設定します。

これは機能するように思えますが、多くの組み合わせがある場合、多数のグループを作成および維持する必要があります。

質問:

  • タイトルを自動的に同期させるための最善の方法、または唯一の方法は、このセットアップ(多数の動的グループと、それぞれに独自のデフォルトタイトルを設定)ですか?
  • グループ + 信頼レベルなどの条件に基づいてタイトルを動的に割り当てるために、Discourse コア、Automations、または別のプラグインを使用して、これほど多くの追加グループを管理せずに済む別の方法はありますか?

アドバイスや共有された経験があれば、大歓迎です。よろしくお願いします!

グループメンバーシップ(AまたはB)に基づいてタイトルを設定し、それに基づいてタイトルを追加するコンポーネントがあれば機能しますか?

そうすれば、これらすべての複合サブグループは不要になると思います :thinking:

別のアイデア:おそらく、信頼レベルをタイトルとして自動的に設定するプラグインを、信頼レベルとグループメンバーシップに基づいたより複雑なタイトルの更新のベースとして使用できるかもしれません。

「いいね!」 3

ご提案ありがとうございます。

残念ながら、私自身はプログラミングの経験がないため、プラグインを開発したり変更したりすることはできません。すでにプラグインの作者に、この機能(グループメンバーシップと信頼レベルを組み合わせてタイトルを設定する)を追加できるか、または何かアドバイスがあるか問い合わせています。

もしそれがユーザーのプライマリグループであれば、他のトピックで言及されたように、物事がずっと楽になると思います。

その後、user.primary_group を介してプライマリグループを取得し、user.title を使用してタイトルを設定できます。

@joo add_primary_group_title(デフォルトはオフ)設定を追加しました。これは以下の機能を提供します。

  • ユーザーのプライマリグループをタイトルとして追加します。
  • タイトルの後ろのテキスト、例:

「いいね!」 1

こんにちは!アップデートとサポートをありがとうございます!

以前、要件を明確に説明できていなかったかもしれませんので、分かりやすい例で再度明確にしたいと思います。

たとえば、私たちのフォーラムには主に2つのグループがあるとします。

  • グループA:デザイナー
  • グループB:開発者

各グループについて、異なる信頼レベルを持つユーザーに、次のような完全に異なるタイトルを付けたいと考えています。

デザイナーグループの場合:
信頼レベル1 → 「ジュニアデザイナー」
信頼レベル2 → 「デザイナー」
信頼レベル3 → 「シニアデザイナー」
信頼レベル4 → 「チーフデザイナー」

開発者グループの場合:
信頼レベル1 → 「ジュニア開発者」
信頼レベル2 → 「開発者」
信頼レベル3 → 「シニア開発者」
信頼レベル4 → 「テックリード」

したがって、「デザイナー」グループに所属し、TL3のユーザーのタイトルは「シニアデザイナー」になります。
「開発者」グループに所属し、TL2のユーザーのタイトルは「開発者」になります。

これらのルールを各グループと信頼レベルごとに設定し、ユーザーのグループや信頼レベルが変更されたときにタイトルが自動的に割り当てられるようにしたいです。

この達成方法について何かアドバイスをいただけますでしょうか、またはこの機能をプラグインに新機能として追加することを検討していただけますでしょうか?

どうぞよろしくお願いいたします!

「いいね!」 1

また、テストサイトの http://ask.discourse.com/ でこれを実現しようとしています。
プログラミング経験がないため、自分で実装できるかどうかはわかりません。

テキストボックスにプレースホルダー値(例:{group_nane})を使用すると、タイトルを編集しやすくなる可能性があります。確認してみます。

以下を確認するとよいでしょう。

こんにちは!

私のニーズに合わせてプラグインを修正しましたので、行ったこと、現在のワークフロー、およびいくつか質問/アドバイスを共有したいと思います。


1. 私の修正内容

ファイルパスと内容:

ファイル: app/jobs/scheduled/update-all-titles.rb

# frozen_string_literal: true

module AddTitleBasedOnTrustLevel
  class UpdateTitles < ::Jobs::Scheduled
    every SiteSetting.update_title_frequency.hours

    def execute(args)
      group_titles = JSON.parse(SiteSetting.group_trust_level_titles || "{}")

      User.find_each do |user|
        # 管理者とモデレーターはスキップし、タイトルを更新しない
        next if user.admin? || user.moderator?

        group_id = user.primary_group_id
        next unless group_id

        group = Group.find_by(id: group_id)
        next unless group

        group_key = group.name.downcase
        tl = user.trust_level

        titles = group_titles[group_key]
        next unless titles.is_a?(Array)
        next unless tl >= 1 && tl <= 4

        new_title = titles[tl]
        next unless new_title.present?

        user.update_column(:title, new_title) if user.title != new_title
      end
    end
  end
end

ファイル: config/settings.yml

plugins:
  add_title_based_on_trust_level_enabled:
    default: false
    client: true
  group_trust_level_titles:
    default: '{"designers": ["", "Junior Designer", "Designer", "Senior Designer", "Chief Designer"], "developers": ["", "Junior Developer", "Developer", "Senior Developer", "Tech Lead"]}'
    type: string
    client: true
    multiline: true
  update_title_frequency:
    default: 24
    type: integer

2. テスト方法

現在、rails console を介してこのロジックを手動で実行し、機能が動作するかどうかを確認しています。要件に従って、ユーザーのタイトルが一括で更新されます。


3. プラグイン設定エントリの問題

/admin/plugins ページにこのプラグインの「設定」ボタンが表示されません。現在、設定を変更するには、直接 /admin/plugins/add-title-based-on-trust-level/settings にアクセスする必要があります。
設定ボタンまたはリンクをプラグインページに表示して、アクセスしやすくする方法はありますか?


4. 現在の設定

これが私の現在のJSON設定です(スクリーンショットも添付します):

{
  "designers": ["", "Junior Designer", "Designer", "Senior Designer", "Chief Designer"],
  "developers": ["", "Junior Developer", "Developer", "Senior Developer", "Tech Lead"]
}


5. 質問 / 可能な改善点

  • このアプローチ(すべてのユーザーをループしてタイトルを更新する)は、ユーザーが多い場合にパフォーマンスの問題を引き起こすリスクはありますか?これに対するより良いベストプラクティスはありますか?
  • スケジュールジョブまたは管理設定UIの最適化に関するアドバイスはありますか?
  • 私の方法に、注意すべき安全でない点や問題点はありますか?

素晴らしい仕事とこの便利なプラグインに心から感謝いたします!
提案があれば、または将来的にグループ+信頼レベルのタイトル設定を改善する予定があれば、ぜひご意見をお聞かせください。

「いいね!」 2

@joo 素晴らしいアイデアですね!

もしプラグインを今見てもらえれば、私も同様のことを行ったと思います(最終テストを実行していました)。各ユーザーをループ処理しているようですが、大規模なフォーラムでは時間がかかる可能性があります。

そのため、SQL UPDATEを使用しました。

(Ask Discourseのクエリを適応させて修正しました)

これにより、tl1_title_on_promotion設定で、Junior {group_name}のようなものを使用できるようになり、タイトルはJunior Developerになります。

機能させるためには、add_primary_group_titleもオンにする必要があることに注意してください。

「いいね!」 1

説明ありがとうございます。これで {group_name} テンプレートの仕組みが理解できました。

しかし、これはまさに私が言いたかったロジックの違いです。私のコア要件は、異なるユーザーグループに基づいて、同じ信頼レベルに対して完全に異なるタイトルの構造を適用できることです。

たとえば、信頼レベル3の場合:

  • 「Designers」グループのタイトルは「Senior Designer」であるべきです。
  • 「Developers」グループのタイトルは「Tech Lead」であるべきです。

これらの2つのタイトルは、完全に異なる構造を持っています。

AIを使ってこの機能を実装しようとしましたが、成功しませんでした。このより詳細なロジックをサポートするようにプラグインを変更することは可能でしょうか?

ああ、それでは誤解していたようです。

では、上記のコードは機能しましたか?

いいえ、以前試したAIのコードもうまくいきませんでした。すべて設定した後、何も起こりませんでした。

最新の試みの完全なコードをここに表示したかったのです。何か間違っている点が見つけられるのではないかと期待していました。

1. plugin.rb

# name: add-title-by-group-trust-level
# about: assign titles via primary group + trust level using SQL
# version: 0.2
# authors: your-name

# 注意: ジョブファイルをロードするために 'require' 行が必要かどうかはわかりません。
# これが欠けている部分であると疑っています。
enabled_site_setting :add_title_by_group_trust_enabled

2. app/jobs/scheduled/update-all-titles.rb

module ::Jobs
  class UpdateTitles < ::Jobs::Scheduled
    every SiteSetting.update_title_frequency.hours

    def execute(args)
      return unless SiteSetting.add_title_by_group_trust_enabled

      mappings = JSON.parse(SiteSetting.group_trust_level_titles || '{}')

      User.transaction do
        mappings.each do |group_key, titles|
          next unless titles.is_a?(Array)

          (1...titles.size).each do |tl|
            title = titles[tl]
            next if title.blank?

            group = Group.find_by("LOWER(name) = ?", group_key.downcase)
            next unless group

            User.where(primary_group_id: group.id, trust_level: tl, admin: false, moderator: false)
                .where.not(title: title)
                .update_all(title: title)
          end
        end
      end
    end
  end
end

3. config/settings.yml

plugins:
  add_title_by_group_trust_enabled:
    default: false
    client: true
  group_trust_level_titles:
    default: '{"designers":["","Junior Designer","Designer","Senior Designer","Chief Designer"],"developers":["","Junior Developer","Developer","Senior Developer","Tech Lead"]}'
    type: string
    client: true
    multiline: true
  update_title_frequency:
    default: 24
    type: integer

サイト設定での設定方法:

group_trust_level_titles 設定にこのJSONを貼り付けました。

{
  "designers": ["", "Junior Designer", "Designer", "Senior Designer", "Chief Designer"],
  "developers": ["", "Junior Developer", "Developer", "Senior Developer", "Tech Lead"]
}

問題点:

UpdateTitles ジョブが Sidekiq スケジューラ(/sidekiq/scheduler)に表示されません。

しかし、AIが提示した方法に従ってRailsコンソールでテストしたところ、コアロジックは完全に機能し、条件を満たすすべてのユーザーが正しく表示されました。

これがRailsコンソールで使用したテストスクリプトです。

mappings = JSON.parse(SiteSetting.group_trust_level_titles || '{}')

mappings.each do |group_key, titles|
  next unless titles.is_a?(Array)

  (1...titles.size).each do |tl|
    title = titles[tl]
    next if title.blank?

    group = Group.find_by("LOWER(name) = ?", group_key.downcase)
    unless group
      puts "Could not find group: #{group_key}"
      next
    end

    users = User.where(primary_group_id: group.id, trust_level: tl, admin: false, moderator: false)
                .where.not(title: title)
    next if users.empty?

    puts "====== Group: #{group.name} Trust Level: #{tl} New Title: '#{title}' ======"
    users.each do |user|
      puts "User id:#{user.id}, username:#{user.username}, current title:'#{user.title}'"
    end
  end
end

したがって、ロジック自体は正しいようですが、Discourseがスケジュールされたジョブを認識していないようです。いずれにせよ、変更を加えれば加えるほど、さらに混乱してきます。これが正しいアプローチなのかどうかわかりませんし、コーディング方法がわからないので、実装するのは非常に難しいと感じています。もっと良い方法はありますか?

オブジェクト設定の使用を検討してみてはいかがでしょうか。

信頼レベル、グループ、タイトルなどのフィールドがあります。

「いいね!」 1

アップデートの状況と、協力してくれたすべての方への感謝をお伝えしたいと思います。

最新の変更により、プラグインは意図したとおりに動作するようになりました!ユーザーのプライマリグループと信頼レベルに基づいて、異なるタイトルを正しく割り当てます。

以下に最終的な動作コードを投稿します。正しく動作しているようですが、私は開発者ではないため、見落としている改善点や最適化の余地があるかどうか疑問に思っています。

app/jobs/scheduled/update-all-titles.rb

# frozen_string_literal: true

module ::Jobs
  class AssignGroupBasedTitles < ::Jobs::Scheduled
    every SiteSetting.update_title_frequency.hours

    def execute(args)
      return unless SiteSetting.add_title_by_group_trust_enabled

      # 設定値を取得します。これは現在JSON文字列です。
      rules_json_string = SiteSetting.group_based_title_rules
      return if rules_json_string.blank?

      begin
        # これが最も重要な修正です:JSON文字列を手動でRuby配列に解析します。
        rules = JSON.parse(rules_json_string)
      rescue JSON::ParserError
        # JSON形式が間違っている場合、タスクの失敗を防ぐために直接終了します。
        Rails.logger.error("Group-Based Titles Plugin: Failed to parse group_based_title_rules JSON.")
        return
      end
      
      return unless rules.is_a?(Array) && rules.present?

      User.transaction do
        rules.each do |rule|
          group_id = rule["group_id"]
          trust_level = rule["trust_level"]
          title = rule["title"]

          next if group_id.blank? || trust_level.blank? || title.blank?

          User.where(primary_group_id: group_id, trust_level: trust_level)
              .where.not(title: title)
              .update_all(title: title)
        end
      end
    end
  end
end

config/settings.yml

plugins:
  add_title_by_group_trust_enabled:
    default: true
    client: true

  # これはtype: objectsでなければなりません。これがエラーの原因でした。
  group_based_title_rules:
    type: objects
    default: []
    schema:
      properties:
        group_id:
          type: integer
          name: "User Group"
          component: "group-chooser"
        trust_level:
          type: integer
          name: "Trust Level"
          min: 1
          max: 4
        title:
          type: string
          name: "Title"
  
  update_title_frequency:
    default: 24
    type: integer

plugin.rb

# frozen_string_literal: true

# name: add-title-by-group-trust-level
# about: Assign titles based on primary group and trust level.
# version: 2.1.0
# authors: Your Name

enabled_site_setting :add_title_by_group_trust_enabled

after_initialize do
  require_relative "./app/jobs/scheduled/update-all-titles.rb"
end
「いいね!」 1