Melhor Prática para Automatizar Títulos por Combinações de Grupo + Nível de Confiança

Olá,

Estou procurando a melhor maneira de atribuir automaticamente títulos de usuário com base em uma combinação de associação de grupo e nível de confiança. Por exemplo:

  • Se um usuário estiver no grupo A e tiver o nível de confiança 1, seu título deverá ser “A TL1”
  • Se um usuário estiver no grupo A e tiver o nível de confiança 2, seu título deverá ser “A TL2”
  • Se um usuário estiver no grupo B e tiver o nível de confiança 1, seu título deverá ser “B TL1”
  • …e assim por diante

Pelo que encontrei até agora, o método principal é:

  1. Criar um grupo separado para cada combinação de grupo + nível de confiança (por exemplo, a-tl1, a-tl2, b-tl1, etc.) usando o plugin Dynamic Groups,
  2. Definir um título padrão para cada um desses grupos.

Embora isso pareça funcionar, requer a criação e manutenção de um grande número de grupos se houver muitas combinações.

Minhas perguntas:

  • Essa configuração (muitos grupos dinâmicos e cada um com seu próprio título padrão) é a melhor ou única maneira de manter os títulos sincronizados automaticamente?
  • Existe outra abordagem (usando o core do Discourse, Automações ou outro plugin) para atribuir títulos dinamicamente com base em condições como grupo + nível de confiança, sem ter que gerenciar tantos grupos adicionais?

Qualquer conselho ou experiências compartilhadas seriam muito apreciados. Agradeço antecipadamente!

Funcionaria para você configurar o título com base na associação ao grupo (A ou B) e ter um componente que adiciona o título com base no nível de confiança por trás disso?

Acho que então você não precisaria de todos esses subgrupos combinados :thinking:

Outra ideia: talvez o plugin que define automaticamente o nível de confiança como título possa ser usado como base para uma atualização de título mais complexa com base no nível de confiança e na associação ao grupo.

3 curtidas

Obrigado por suas sugestões

Infelizmente, eu não tenho nenhuma experiência em programação, então não sou capaz de desenvolver ou modificar plugins. Já entrei em contato com o autor do plugin para perguntar se esse recurso (combinando associação de grupo e nível de confiança para títulos) poderia ser adicionado, ou se ele tem algum conselho.

Se for o grupo principal do usuário, acho que, como você mencionou no outro tópico, isso tornaria as coisas muito mais fáceis.

Em seguida, você pode obter o grupo principal dele via user.primary_group e, em seguida, definir o título usando user.title.

@joo Adicionei a configuração add_primary_group_title (padrão desativado) que:

  • adiciona o grupo primário do usuário como título
  • texto atrás do título, por exemplo:

          pode ser editado usando as configurações como antes.

Usei uma pitada da magia do ask.discourse.com.

P.S. Se você está se perguntando como eu indentei o ‘pode’, usei  . Desculpem, pessoal.

1 curtida

Olá! Obrigado pela sua atualização e suporte!

Talvez eu não tenha explicado meu requisito com clareza antes, então quero esclarecê-lo novamente com um exemplo fácil de entender:

Suponha que nosso fórum tenha dois grupos principais:

  • Grupo A: Designers
  • Grupo B: Desenvolvedores

Para cada grupo, quero que usuários com diferentes níveis de confiança recebam um título completamente diferente, assim:

Para o grupo Designers:
Nível de Confiança 1 → “Designer Júnior”
Nível de Confiança 2 → “Designer”
Nível de Confiança 3 → “Designer Sênior”
Nível de Confiança 4 → “Designer Chefe”

Para o grupo Desenvolvedores:
Nível de Confiança 1 → “Desenvolvedor Júnior”
Nível de Confiança 2 → “Desenvolvedor”
Nível de Confiança 3 → “Desenvolvedor Sênior”
Nível de Confiança 4 → “Tech Lead”

Portanto, se alguém estiver no grupo “Designers” com TL3, o título dela deve ser “Designer Sênior”.
Se ela estiver no grupo “Desenvolvedores” com TL2, o título deve ser “Desenvolvedor”.

Gostaria de poder definir essas regras para cada grupo e nível de confiança, e ter os títulos atribuídos automaticamente conforme os grupos ou níveis de confiança dos usuários mudam.

Você teria algum conselho sobre como alcançar isso, ou consideraria adicionar isso como um novo recurso em seu plugin?

Muito obrigado!

1 curtida

Além disso, estou tentando fazer isso no meu site de teste: http://ask.discourse.com/.
Não tenho experiência em programação, então não tenho certeza se é possível implementar isso sozinho.

Posso usar um valor de espaço reservado, por exemplo, {nome_do_grupo} na caixa de texto para que seja mais fácil editar o título. Vou dar uma olhada.

Você pode querer conferir:

Olá!

Modifiquei o plugin para atender às minhas necessidades e gostaria de compartilhar o que fiz, meu fluxo de trabalho atual e algumas perguntas/solicitações de conselhos.


1. Minhas Modificações

Caminho e conteúdo do arquivo:

Arquivo: 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|
        # Pula administradores e moderadores, não atualiza seus títulos
        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

Arquivo: 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. Como Testei

Atualmente estou executando essa lógica manualmente via console do Rails para verificar se a função funciona. Ela atualiza os títulos dos usuários em massa de acordo com meus requisitos.


3. Problema de Entrada de Configurações do Plugin

Não há um botão de “Configurações” para este plugin na página /admin/plugins. No momento, para alterar a configuração, preciso visitar /admin/plugins/add-title-based-on-trust-level/settings diretamente. Existe uma maneira de fazer o botão ou link de configurações aparecer na página de Plugins para facilitar o acesso?


4. Minhas Configurações Atuais

Esta é minha configuração JSON atual (anexarei uma captura de tela também):

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


5. Perguntas / Possíveis Melhorias

  • Essa abordagem (iterar por cada usuário e atualizar seu título) corre o risco de problemas de desempenho se houver muitos usuários? Existe uma melhor prática para isso?
  • Algum conselho sobre otimização, seja para o job agendado ou para a interface de configurações do administrador?
  • Há algo inseguro ou problemático no meu método com o qual eu deva ter cuidado?

Muito obrigado pelo seu ótimo trabalho e por este plugin útil!
Se você tiver alguma sugestão, ou se planeja melhorar a configuração de títulos de grupo + nível de confiança no futuro, adoraria ouvir suas opiniões.

2 curtidas

@joo Ideia muito legal!

Se você olhar o plugin agora, acho que fiz isso também (estava executando alguns testes finais). Vejo que você percorreu cada usuário, mas em fóruns grandes, isso pode demorar.

Então, eu fiz um SQL UPDATE:

(Adaptei a query do Ask Discourse e a modifiquei)

Dessa forma, na configuração tl1_title_on_promotion, você poderá usar algo como Júnior {group_name}, então o título se tornaria Júnior Desenvolvedor.

Note que você também teria que marcar add_primary_group_title para que funcione.

1 curtida

Obrigado pela explicação, agora entendo como funciona o seu modelo {group_name}.

Mas é exatamente isso que eu quis dizer com a diferença na lógica. Meu requisito principal é poder aplicar estruturas de título completamente diferentes para o mesmo nível de confiança, com base em diferentes grupos de usuários.

Por exemplo, para o Nível de Confiança 3:

  • O título para o grupo “Designers” deve ser “Designer Sênior”.
  • O título para o grupo “Developers” deve ser “Tech Lead”.

Esses dois títulos têm estruturas completamente diferentes.

Eu tentei implementar esse recurso com uma IA, mas não tive sucesso. Eu estava me perguntando se seria possível para você modificar o plugin para suportar essa lógica mais granular?

Ah, acho que entendi errado então.

Então o seu código acima funcionou?

Não, o código anterior que tentei com uma IA também não funcionou. Depois de configurar tudo, nada aconteceu.

Eu queria te mostrar o código completo da minha última tentativa. Eu esperava que você pudesse ver o que estou fazendo de errado.

1. plugin.rb

# name: add-title-by-group-trust-level
# about: atribui títulos por grupo primário + nível de confiança usando SQL
# version: 0.2
# authors: seu-nome

# Nota: Não tenho certeza se preciso de uma linha 'require' aqui para carregar o arquivo de job.
# Suspeito que esta possa ser a peça que falta.
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

Aqui está como eu configurei nas Configurações do Site:

Eu colei este JSON na configuração group_trust_level_titles:

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

O Problema:

O job UpdateTitles não aparece no agendador do Sidekiq (/sidekiq/scheduler).

No entanto, eu testei no console Rails de acordo com o método que a IA me deu, e a lógica principal está perfeitamente bem, imprimindo corretamente todos os usuários que atendem às condições.

Este é o script de teste que usei no 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 "Não foi possível encontrar o grupo: #{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 "====== Grupo: #{group.name} Nível de Confiança: #{tl} Novo Título: '#{title}' ======"
    users.each do |user|
      puts "Usuário id:#{user.id}, username:#{user.username}, título atual:'#{user.title}'"
    end
  end
end

Portanto, parece que a lógica em si está correta, mas o Discourse não está registrando o job agendado. De qualquer forma, quanto mais eu tento mudar, mais confuso fica… Não tenho certeza se essa é a abordagem correta, e como não sei codificar, parece muito difícil implementar isso. Você tem um método melhor?

Hmm… talvez você queira usar as configurações de objeto:

Com campos como Nível de Confiança, grupo, título.

1 curtida

Só queria dar uma atualização e agradecer a todos que ajudaram.

Com as últimas alterações, o plugin agora está funcionando exatamente como eu pretendia! Ele atribui corretamente títulos diferentes com base no grupo principal e no nível de confiança do usuário.

Estou postando o código final de funcionamento abaixo. Parece estar correto, mas como não sou um desenvolvedor, estava me perguntando se há alguma área para melhoria ou otimização que eu possa ter perdido.

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

      # Obtém o valor da configuração, que agora é uma string JSON
      rules_json_string = SiteSetting.group_based_title_rules
      return if rules_json_string.blank?

      begin
        # Esta é a correção mais crucial: analisar manualmente a string JSON em um array Ruby
        rules = JSON.parse(rules_json_string)
      rescue JSON::ParserError
        # Se o formato JSON estiver incorreto, saia diretamente para evitar falha na tarefa
        Rails.logger.error("Plugin Títulos Baseados em Grupo: Falha ao analisar JSON group_based_title_rules.")
        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

  # Isso DEVE ser do tipo: objects. Esta foi a origem do erro.
  group_based_title_rules:
    type: objects
    default: []
    schema:
      properties:
        group_id:
          type: integer
          name: "Grupo de Usuários"
          component: "group-chooser"
        trust_level:
          type: integer
          name: "Nível de Confiança"
          min: 1
          max: 4
        title:
          type: string
          name: "Título"
  
  update_title_frequency:
    default: 24
    type: integer

plugin.rb

# frozen_string_literal: true

# name: add-title-by-group-trust-level
# about: Atribui títulos com base no grupo principal e nível de confiança.
# version: 2.1.0
# authors: Seu Nome

enabled_site_setting :add_title_by_group_trust_enabled

after_initialize do
  require_relative "./app/jobs/scheduled/update-all-titles.rb"
end
1 curtida