Beste praktijk voor het automatiseren van titels op basis van groeps- en vertrouwensniveaucombinaties

Hallo,

Ik ben op zoek naar de beste manier om automatisch gebruikersnamen toe te wijzen op basis van een combinatie van groepslidmaatschap en vertrouwensniveau. Bijvoorbeeld:

  • Als een gebruiker in groep A zit en vertrouwensniveau 1 heeft, moet hun titel “A TL1” zijn
  • Als een gebruiker in groep A zit en vertrouwensniveau 2 heeft, moet hun titel “A TL2” zijn
  • Als een gebruiker in groep B zit en vertrouwensniveau 1 heeft, moet hun titel “B TL1” zijn
  • …enzovoort

Voor zover ik tot nu toe heb gevonden, is de belangrijkste methode:

  1. Maak een aparte groep voor elke groep + vertrouwensniveau combinatie (bijv. a-tl1, a-tl2, b-tl1, etc.) met behulp van de Dynamic Groups plugin,
  2. Stel een standaardtitel in voor elk van deze groepen.

Hoewel dit lijkt te werken, vereist het het aanmaken en onderhouden van een groot aantal groepen als er veel combinaties zijn.

Mijn vragen:

  • Is deze opstelling (veel dynamische groepen en elk met zijn eigen standaardtitel) de beste of enige manier om titels automatisch gesynchroniseerd te houden?
  • Is er een andere aanpak (met behulp van Discourse core, Automations, of een andere plugin) om titels dynamisch toe te wijzen op basis van voorwaarden zoals groep + vertrouwensniveau, zonder zoveel extra groepen te hoeven beheren?

Alle adviezen of gedeelde ervaringen worden zeer gewaardeerd. Alvast bedankt!

Would it work for you to configure the title based on the group membership (A or B) and have a component that adds the title based on the trust level behind that?

I think then you wouldn’t need all those combined subgroups :thinking:

Another idea: Maybe the plugin which automatically sets the trust level as the title could be used as a base for a more complex title update based on trust level and group membership

3 likes

Bedankt voor uw suggesties

Helaas heb ik zelf geen programmeerervaring, dus ik kan geen plugins ontwikkelen of aanpassen. Ik heb al contact opgenomen met de auteur van de plugin om te vragen of deze functie (combineren van groepslidmaatschap en vertrouwensniveau voor titels) kan worden toegevoegd, of dat hij/zij enig advies heeft.

Als het de primaire groepen van de gebruiker zijn, denk ik, zoals je in het andere onderwerp noemde, dat dit de zaken een stuk gemakkelijker zou maken.

Je kunt dan hun primaire groep ophalen via user.primary_group en vervolgens de titel instellen met user.title.

@joo I have added the setting add_primary_group_title (default off) that:

  • adds the user’s primary group as the title
  • text behind the title, eg:

         can be edited using the settings as before.

Used a hint of ask.discourse.com magic.

P.S. If you’re wondering how I indented the ‘can’, I used  . Sorry guys.

1 like

Hallo! Bedankt voor je update en ondersteuning!

Ik heb mijn vereiste mogelijk niet duidelijk uitgelegd, dus ik wil het nogmaals verduidelijken met een eenvoudig te begrijpen voorbeeld:

Stel dat ons forum twee hoofdgroepen heeft:

  • Groep A: Ontwerpers
  • Groep B: Ontwikkelaars

Voor elke groep wil ik dat gebruikers met verschillende vertrouwensniveaus een compleet andere titel krijgen, zoals dit:

Voor de groep Ontwerpers:
Vertrouwensniveau 1 → “Junior Ontwerper”
Vertrouwensniveau 2 → “Ontwerper”
Vertrouwensniveau 3 → “Senior Ontwerper”
Vertrouwensniveau 4 → “Hoofdontwerper”

Voor de groep Ontwikkelaars:
Vertrouwensniveau 1 → “Junior Ontwikkelaar”
Vertrouwensniveau 2 → “Ontwikkelaar”
Vertrouwensniveau 3 → “Senior Ontwikkelaar”
Vertrouwensniveau 4 → “Tech Lead”

Dus, als iemand in “Ontwerpers” zit met TL3, zou hun titel “Senior Ontwerper” moeten zijn.
Als ze in “Ontwikkelaars” zitten met TL2, zou de titel “Ontwikkelaar” moeten zijn.

Ik zou deze regels voor elke groep en elk vertrouwensniveau willen kunnen instellen, en dat titels automatisch worden toegewezen naarmate de groepen of vertrouwensniveaus van gebruikers veranderen.

Heeft u enig advies over hoe dit te bereiken, of zou u overwegen dit als een nieuwe functie in uw plugin toe te voegen?

Heel erg bedankt!

1 like

Also, I am trying to achieve this on my test site: http://ask.discourse.com/.
I don’t have programming experience, so I am not sure if it’s possible to implement this myself.

I might use a placeholder value, e.g. {group_nane} in the text box so that it can be easier to edit the title. I’ll take a look.

You might want to check out:

Hi!

I’ve modified the plugin to fit my needs, and I’d like to share what I did, my current workflow, and a few questions/requests for advice.


1. My Modifications

File path and content:

File: 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|
        # Skip admins and moderators, do not update their titles
        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

File: 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. How I Tested

I am currently manually running this logic via rails console to check if the function works. It does update user titles in bulk according to my requirements.


3. Plugin Settings Entry Issue

There is no “Settings” button for this plugin on the /admin/plugins page. Right now, to change the config, I have to visit /admin/plugins/add-title-based-on-trust-level/settings directly.
Is there a way to have the settings button or link appear on the Plugins page for easier access?


4. My Current Settings

This is my current JSON configuration (I will attach a screenshot as well):

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


5. Questions / Possible Improvements

  • Does this approach (looping through every user and updating their title) risk performance issues if there are a lot of users? Is there a better best-practice for this?
  • Any advice on optimization, either for the scheduled job or for the admin settings UI?
  • Is there anything unsafe or problematic with my method that I should be careful about?

Thank you very much for your great work and this useful plugin!
If you have any suggestions, or if you plan to improve group+trust level title config in the future, I would love to hear your thoughts.

2 likes

@joo Really neat idea!

If you look at the plugin now, I think I did this too (was running some final tests). I see you looped through each user, but in big forums, this may take a while.

So, I did a SQL UPDATE:

(I adapted Ask Discourse’s query and modified it)

This way, in the setting tl1_title_on_promotion, you should be able to use something like Junior {group_name}, so then the title would become Junior Developer.

Note that you would also have to tick add_primary_group_title for it to work.

1 like

Bedankt voor de uitleg, ik begrijp nu hoe je {group_name} template werkt.

Maar dit is precies wat ik bedoelde met het verschil in logica. Mijn kernvereiste is om volledig verschillende titelstructuren te kunnen toepassen voor hetzelfde vertrouwensniveau, gebaseerd op verschillende gebruikersgroepen.

Bijvoorbeeld, voor Vertrouwensniveau 3:

  • De titel voor de groep “Designers” zou “Senior Designer” moeten zijn.
  • De titel voor de groep “Developers” zou “Tech Lead” moeten zijn.

Deze twee titels hebben volledig verschillende structuren.

Ik heb geprobeerd deze functie te implementeren met een AI, maar dat is me niet gelukt. Ik vroeg me af of het misschien mogelijk is om de plugin aan te passen om deze meer gedetailleerde logica te ondersteunen?

Ah, I think I misunderstood you then.

So did your code above work?

Nee, de vorige code die ik met een AI probeerde werkte ook niet. Nadat ik alles had ingesteld, gebeurde er helemaal niets.

Ik wilde je de volledige code van mijn laatste poging laten zien. Ik hoopte dat je misschien kon zien wat ik verkeerd doe.

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

# Note: Ik weet niet zeker of ik hier een 'require'-regel nodig heb om het jobbestand te laden.
# Ik vermoed dat dit het ontbrekende stukje is.
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

Dit is hoe ik het heb geconfigureerd in de Site-instellingen:

Ik heb deze JSON in de group_trust_level_titles-instelling geplakt:

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

Het Probleem:
De UpdateTitles-job verschijnt niet in de Sidekiq-scheduler (/sidekiq/scheduler).

Ik heb het echter getest in de Rails-console volgens de methode die de AI me gaf, en de kernlogica is perfect in orde, waarbij alle gebruikers die aan de voorwaarden voldoen correct worden afgedrukt.

Dit is het testscript dat ik in de Rails-console heb gebruikt:

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

Het lijkt er dus op dat de logica zelf correct is, maar Discourse de geplande taak niet registreert. Hoe dan ook, hoe meer ik probeer het te veranderen, hoe verwarrender het wordt… Ik weet niet zeker of dit de juiste aanpak is, en omdat ik niet weet hoe ik moet coderen, voelt het erg moeilijk om dit te implementeren. Heb je een betere methode?

Hmm… maybe you want to use object settings:

With fields like Trust Level, group, title.

1 like

Graag een update en bedankt aan iedereen die heeft geholpen.

Met de laatste wijzigingen werkt de plugin nu precies zoals ik bedoeld had! Het kent correct verschillende titels toe op basis van de primaire groep en het vertrouwensniveau van de gebruiker.

Ik plaats hieronder de definitieve werkende code. Het lijkt correct, maar aangezien ik geen ontwikkelaar ben, vroeg ik me af of er gebieden zijn voor verbetering of optimalisatie die ik misschien heb gemist.

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

      rules_json_string = SiteSetting.group_based_title_rules
      return if rules_json_string.blank?

      begin
        # Parseer de JSON-tekenreeks handmatig naar een Ruby-array.
        rules = JSON.parse(rules_json_string)
      rescue JSON::ParserError
        # Als de JSON ongeldig is, log dan een fout en sluit af om te voorkomen dat de taak mislukt.
        Rails.logger.error("Group-Based Titles Plugin: Kon group_based_title_rules JSON niet parsen.")
        return
      end
      
      # Veiligheidscontrole om ervoor te zorgen dat de geparseerde regels een niet-lege array zijn.
      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

  group_based_title_rules:
    type: objects
    default: []
    schema:
      properties:
        group_id:
          type: integer
          name: "Gebruikersgroep"
          component: "group-chooser"
        trust_level:
          type: integer
          name: "Vertrouwensniveau"
          min: 1
          max: 4
        title:
          type: string
          name: "Titel"
  
  update_title_frequency:
    default: 24
    type: integer

plugin.rb

# frozen_string_literal: true

# name: add-title-by-group-trust-level
# about: Kent titels toe op basis van primaire groep en vertrouwensniveau.
# 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 like