Migliore pratica per automatizzare i titoli per combinazioni di gruppi e livelli di fiducia

Ciao,

Sto cercando il modo migliore per assegnare automaticamente i titoli degli utenti in base a una combinazione di appartenenza a gruppi e livello di fiducia. Ad esempio:

  • Se un utente appartiene al gruppo A e ha il livello di fiducia 1, il suo titolo dovrebbe essere “A TL1”
  • Se un utente appartiene al gruppo A e ha il livello di fiducia 2, il suo titolo dovrebbe essere “A TL2”
  • Se un utente appartiene al gruppo B e ha il livello di fiducia 1, il suo titolo dovrebbe essere “B TL1”
  • … e così via

Da quello che ho trovato finora, il metodo principale è:

  1. Creare un gruppo separato per ogni combinazione gruppo + livello di fiducia (ad esempio, a-tl1, a-tl2, b-tl1, ecc.) utilizzando il plugin Gruppi Dinamici,
  2. Impostare un titolo predefinito per ciascuno di questi gruppi.

Sebbene questo sembri funzionare, richiede la creazione e la gestione di un gran numero di gruppi se ci sono molte combinazioni.

Le mie domande:

  • Questa configurazione (molti gruppi dinamici e ognuno con il proprio titolo predefinito) è il modo migliore o l’unico per mantenere i titoli sincronizzati automaticamente?
  • Esiste un altro approccio (utilizzando il core di Discourse, Automations o un altro plugin) per assegnare dinamicamente i titoli in base a condizioni come gruppo + livello di fiducia, senza dover gestire così tanti gruppi aggiuntivi?

Qualsiasi consiglio o esperienza condivisa sarebbe molto apprezzato. Grazie in anticipo!

Funzionerebbe per te configurare il titolo in base all’appartenenza al gruppo (A o B) e avere un componente che aggiunge il titolo in base al livello di fiducia dietro quello?

Penso che non avresti bisogno di tutti quei sottogruppi combinati :thinking:

Un’altra idea: forse il plugin che imposta automaticamente il livello di fiducia come titolo potrebbe essere utilizzato come base per un aggiornamento del titolo più complesso basato sul livello di fiducia e sull’appartenenza al gruppo

3 Mi Piace

Grazie per i tuoi suggerimenti

Purtroppo, non ho alcuna esperienza di programmazione, quindi non sono in grado di sviluppare o modificare plugin. Ho già contattato l’autore del plugin per chiedere se questa funzionalità (combinare l’appartenenza al gruppo e il livello di fiducia per i titoli) potesse essere aggiunta, o se avesse qualche consiglio.

Se si tratta dei gruppi primari dell’utente, penso che, come hai menzionato nell’altro argomento, ciò renderebbe le cose molto più facili.

Quindi, puoi ottenere il loro gruppo primario tramite user.primary_group e quindi impostare il titolo usando user.title.

@joo Ho aggiunto l’impostazione add_primary_group_title (predefinita su off) che:

  • aggiunge il gruppo primario dell’utente come titolo
  • testo dietro il titolo, ad esempio:

          può essere modificato utilizzando le impostazioni come prima.

Ho usato un pizzico della magia di ask.discourse.com.

P.S. Se ti stai chiedendo come ho indentato il ‘può’, ho usato  . Scusate ragazzi.

1 Mi Piace

Ciao! Grazie per il tuo aggiornamento e supporto!

Potrei non aver spiegato chiaramente il mio requisito in precedenza, quindi voglio chiarirlo di nuovo con un esempio di facile comprensione:

Supponiamo che il nostro forum abbia due gruppi principali:

  • Gruppo A: Designer
  • Gruppo B: Sviluppatori

Per ogni gruppo, voglio che gli utenti con diversi livelli di fiducia ricevano un titolo completamente diverso, come questo:

Per il gruppo Designer:
Livello di Fiducia 1 → “Junior Designer”
Livello di Fiducia 2 → “Designer”
Livello di Fiducia 3 → “Senior Designer”
Livello di Fiducia 4 → “Chief Designer”

Per il gruppo Sviluppatori:
Livello di Fiducia 1 → “Junior Developer”
Livello di Fiducia 2 → “Developer”
Livello di Fiducia 3 → “Senior Developer”
Livello di Fiducia 4 → “Tech Lead”

Quindi, se qualcuno è nel gruppo “Designer” con TL3, il suo titolo dovrebbe essere “Senior Designer”.
Se è nel gruppo “Developer” con TL2, il titolo dovrebbe essere “Developer”.

Vorrei poter impostare queste regole per ogni gruppo e livello di fiducia, e avere i titoli assegnati automaticamente al cambiare dei gruppi o dei livelli di fiducia degli utenti.

Avete qualche consiglio su come raggiungere questo obiettivo, o prendereste in considerazione l’aggiunta di questa funzionalità al vostro plugin?

Grazie mille!

1 Mi Piace

Inoltre, sto cercando di ottenere questo sul mio sito di prova: http://ask.discourse.com/.
Non ho esperienza di programmazione, quindi non sono sicuro se sia possibile implementarlo da solo.

Potrei usare un valore segnaposto, ad esempio {group_nane} nella casella di testo in modo che sia più facile modificare il titolo. Darò un’occhiata.

Potresti voler dare un’occhiata a:

Ciao!

Ho modificato il plugin per adattarlo alle mie esigenze e vorrei condividere ciò che ho fatto, il mio attuale flusso di lavoro e alcune domande/richieste di consulenza.


1. Le mie modifiche

Percorso e contenuto del file:

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|
        # Salta amministratori e moderatori, non aggiornare i loro titoli
        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. Come ho testato

Attualmente sto eseguendo manualmente questa logica tramite la console di Rails per verificare se la funzione funziona. Aggiorna correttamente i titoli degli utenti in blocco secondo i miei requisiti.


3. Problema di inserimento delle impostazioni del plugin

Non c’è un pulsante “Impostazioni” per questo plugin nella pagina /admin/plugins. Al momento, per modificare la configurazione, devo visitare direttamente /admin/plugins/add-title-based-on-trust-level/settings.
C’è un modo per far apparire il pulsante o il link delle impostazioni nella pagina dei plugin per un accesso più facile?


4. Le mie impostazioni attuali

Questa è la mia attuale configurazione JSON (allegherò anche uno screenshot):

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


5. Domande / Possibili miglioramenti

  • Questo approccio (iterare su ogni utente e aggiornare il suo titolo) rischia problemi di prestazioni se ci sono molti utenti? Esiste una migliore best practice per questo?
  • Qualche consiglio sull’ottimizzazione, sia per il job pianificato che per l’interfaccia utente delle impostazioni di amministrazione?
  • C’è qualcosa di insicuro o problematico nel mio metodo di cui dovrei essere cauto?

Grazie mille per il tuo grande lavoro e per questo utile plugin!
Se hai suggerimenti, o se prevedi di migliorare la configurazione dei titoli per gruppo+livello di fiducia in futuro, mi piacerebbe sentire i tuoi pensieri.

2 Mi Piace

@joo Idea davvero fantastica!

Se dai un’occhiata al plugin ora, penso di averlo fatto anche io (stavo eseguendo alcuni test finali). Vedo che hai ciclato attraverso ogni utente, ma nei forum di grandi dimensioni, questo potrebbe richiedere tempo.

Quindi, ho eseguito un SQL UPDATE:

(Ho adattato la query di Ask Discourse e l’ho modificata)

In questo modo, nell’impostazione tl1_title_on_promotion, dovresti essere in grado di usare qualcosa come Junior {group_name}, così il titolo diventerebbe Junior Developer.

Nota che dovresti anche selezionare add_primary_group_title affinché funzioni.

1 Mi Piace

Grazie per la spiegazione, ora capisco come funziona il tuo template {group_name}.

Ma questo è esattamente ciò che intendevo con la differenza di logica. Il mio requisito fondamentale è poter applicare strutture di titoli completamente diverse per lo stesso livello di fiducia, in base a diversi gruppi di utenti.

Ad esempio, per il Livello di Fiducia 3:

  • Il titolo per il gruppo “Designer” dovrebbe essere “Senior Designer”.
  • Il titolo per il gruppo “Developer” dovrebbe essere “Tech Lead”.

Questi due titoli hanno strutture completamente diverse.

Ho provato a implementare questa funzionalità con un’IA, ma non ho avuto successo. Mi chiedevo se fosse possibile per te modificare il plugin per supportare questa logica più granulare?

Ah, penso di aver capito male allora.

Quindi il tuo codice sopra ha funzionato?

No, anche il codice precedente che ho provato con un’IA non ha funzionato. Dopo aver configurato tutto, non è successo assolutamente nulla.

Volevo mostrarti il codice completo del mio ultimo tentativo. Speravo che potessi vedere cosa sto sbagliando.

1. plugin.rb

# name: add-title-by-group-trust-level
# about: assegna titoli tramite gruppo primario + livello di fiducia usando SQL
# version: 0.2
# authors: your-name

# Nota: non sono sicuro se ho bisogno di una riga 'require' qui per caricare il file del job.
# Sospetto che questo possa essere il pezzo mancante.
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

Ecco come l’ho configurato nelle Impostazioni del Sito:

Ho incollato questo JSON nell’impostazione group_trust_level_titles:

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

Il Problema:
Il job UpdateTitles non appare nello scheduler di Sidekiq (/sidekiq/scheduler).

Tuttavia, l’ho testato nella console Rails secondo il metodo fornito dall’IA e la logica principale funziona perfettamente, stampando correttamente tutti gli utenti che soddisfano le condizioni.

Questo è lo script di test che ho usato nella console 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 "Impossibile trovare il gruppo: #{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 "====== Gruppo: #{group.name} Livello di fiducia: #{tl} Nuovo titolo: '#{title}' ======"
    users.each do |user|
      puts "ID utente:#{user.id}, nome utente:#{user.username}, titolo attuale:'#{user.title}'"
    end
  end
end

Quindi sembra che la logica in sé sia corretta, ma Discourse non registra il job pianificato. Comunque, più cerco di cambiarlo, più diventa confuso… Non sono sicuro che questo sia l’approccio giusto e, dato che non so programmare, mi sembra molto difficile implementarlo. Hai un metodo migliore?

Hmm… forse vuoi usare le impostazioni degli oggetti:

Con campi come Livello di fiducia, gruppo, titolo.

1 Mi Piace

Volevo solo dare un aggiornamento e ringraziare tutti coloro che hanno aiutato.

Con le ultime modifiche, il plugin ora funziona esattamente come intendevo! Assegna correttamente titoli diversi in base al gruppo primario e al livello di fiducia dell’utente.

Sto pubblicando di seguito il codice funzionante finale. Sembra corretto, ma dato che non sono uno sviluppatore, mi chiedevo se ci fossero aree di miglioramento o ottimizzazione che potrei aver trascurato.

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

      # Ottieni il valore dell'impostazione, che ora è una stringa JSON
      rules_json_string = SiteSetting.group_based_title_rules
      return if rules_json_string.blank?

      begin
        # Questa è la correzione più critica: analizza manualmente la stringa JSON in un array Ruby
        rules = JSON.parse(rules_json_string)
      rescue JSON::ParserError
        # Se il formato JSON è errato, esci direttamente per evitare che il job fallisca
        Rails.logger.error("Plugin Titoli Basati sui Gruppi: Impossibile analizzare 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

  # Questo DEVE essere di tipo: objects. Questa è stata la fonte dell'errore.
  group_based_title_rules:
    type: objects
    default: []
    schema:
      properties:
        group_id:
          type: integer
          name: "Gruppo Utente"
          component: "group-chooser"
        trust_level:
          type: integer
          name: "Livello di Fiducia"
          min: 1
          max: 4
        title:
          type: string
          name: "Titolo"
  
  update_title_frequency:
    default: 24
    type: integer

plugin.rb

# frozen_string_literal: true

# name: add-title-by-group-trust-level
# about: Assegna titoli in base al gruppo primario e al livello di fiducia.
# 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 Mi Piace