Mejor práctica para automatizar títulos por combinaciones de grupo y nivel de confianza

Hola,

Estoy buscando la mejor manera de asignar automáticamente títulos de usuario basándome en una combinación de pertenencia a grupos y nivel de confianza. Por ejemplo:

  • Si un usuario está en el grupo A y tiene nivel de confianza 1, su título debería ser “A TL1”.
  • Si un usuario está en el grupo A y tiene nivel de confianza 2, su título debería ser “A TL2”.
  • Si un usuario está en el grupo B y tiene nivel de confianza 1, su título debería ser “B TL1”.
  • …y así sucesivamente.

Por lo que he encontrado hasta ahora, el método principal es:

  1. Crear un grupo separado para cada combinación de grupo + nivel de confianza (por ejemplo, a-tl1, a-tl2, b-tl1, etc.) usando el plugin Dynamic Groups.
  2. Establecer un título predeterminado para cada uno de estos grupos.

Si bien esto parece funcionar, requiere crear y mantener un gran número de grupos si hay muchas combinaciones.

Mis preguntas:

  • ¿Es esta configuración (muchos grupos dinámicos y cada uno con su propio título predeterminado) la mejor o la única manera de mantener los títulos sincronizados automáticamente?
  • ¿Existe otro enfoque (usando el núcleo de Discourse, Automatizaciones o algún otro plugin) para asignar títulos dinámicamente basándose en condiciones como grupo + nivel de confianza, sin tener que administrar tantos grupos adicionales?

Cualquier consejo o experiencia compartida sería muy apreciado. ¡Gracias de antemano!

¿Funcionaría para ti configurar el título basándose en la pertenencia al grupo (A o B) y tener un componente que añada el título basándose en el nivel de confianza detrás de eso?

Creo que entonces no necesitarías todos esos subgrupos combinados :thinking:

Otra idea: Quizás el plugin que establece automáticamente el nivel de confianza como título podría usarse como base para una actualización de título más compleja basada en el nivel de confianza y la pertenencia al grupo.

3 Me gusta

Gracias por tus sugerencias

Lamentablemente, no tengo experiencia en programación, por lo que no puedo desarrollar ni modificar plugins. Ya me he puesto en contacto con el autor del plugin para preguntarle si se podría añadir esta función (combinar la membresía de grupo y el nivel de confianza para los títulos), o si tiene algún consejo.

Si son los grupos principales del usuario, creo que, como mencionaste en el otro tema, eso facilitaría mucho las cosas.

Luego, puedes obtener su grupo principal a través de user.primary_group y luego establecer el título usando user.title.

@joo He agregado la configuración add_primary_group_title (desactivada por defecto) que:

  • agrega el grupo principal del usuario como título
  • texto detrás del título, por ejemplo:

          se puede editar usando la configuración como antes.

Usé una pizca de la magia de ask.discourse.com.

P.S. Si te preguntas cómo sangré el ‘se puede’, usé  . Lo siento chicos.

1 me gusta

¡Hola! ¡Gracias por tu actualización y apoyo!

Es posible que no haya explicado mi requisito con claridad antes, así que quiero aclararlo nuevamente con un ejemplo fácil de entender:

Supongamos que nuestro foro tiene dos grupos principales:

  • Grupo A: Diseñadores
  • Grupo B: Desarrolladores

Para cada grupo, quiero que los usuarios con diferentes niveles de confianza obtengan un título completamente diferente, así:

Para el grupo de Diseñadores:
Nivel de Confianza 1 → “Diseñador Junior”
Nivel de Confianza 2 → “Diseñador”
Nivel de Confianza 3 → “Diseñador Senior”
Nivel de Confianza 4 → “Diseñador Jefe”

Para el grupo de Desarrolladores:
Nivel de Confianza 1 → “Desarrollador Junior”
Nivel de Confianza 2 → “Desarrollador”
Nivel de Confianza 3 → “Desarrollador Senior”
Nivel de Confianza 4 → “Líder Técnico”

Entonces, si alguien está en “Diseñadores” con TL3, su título debería ser “Diseñador Senior”.
Si están en “Desarrolladores” con TL2, el título debería ser “Desarrollador”.

Me gustaría poder establecer estas reglas para cada grupo y nivel de confianza, y que los títulos se asignen automáticamente a medida que cambian los grupos o niveles de confianza de los usuarios.

¿Podrías compartir algún consejo sobre cómo lograr esto, o considerarías agregar esto como una nueva función en tu plugin?

¡Muchas gracias!

1 me gusta

Además, estoy intentando lograr esto en mi sitio de prueba: http://ask.discourse.com/.
No tengo experiencia en programación, así que no estoy seguro si es posible implementarlo yo mismo.

Es posible que utilice un valor de marcador de posición, por ejemplo, {group_nane} en el cuadro de texto para que sea más fácil editar el título. Lo revisaré.

Quizás quieras echar un vistazo a:

¡Hola!

He modificado el plugin para que se ajuste a mis necesidades y me gustaría compartir lo que hice, mi flujo de trabajo actual y algunas preguntas/solicitudes de asesoramiento.


1. Mis Modificaciones

Ruta y contenido del archivo:

Archivo: 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|
        # Omitir administradores y moderadores, no actualizar sus 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

Archivo: 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. Cómo Probé

Actualmente estoy ejecutando esta lógica manualmente a través de la consola de Rails para verificar si la función funciona. Actualiza los títulos de los usuarios en masa según mis requisitos.


3. Problema de Entrada de Configuración del Plugin

No hay un botón de “Configuración” para este plugin en la página /admin/plugins. En este momento, para cambiar la configuración, tengo que visitar /admin/plugins/add-title-based-on-trust-level/settings directamente. ¿Hay alguna manera de que el botón o enlace de configuración aparezca en la página de Plugins para un acceso más fácil?


4. Mi Configuración Actual

Esta es mi configuración JSON actual (adjuntaré una captura de pantalla también):

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


5. Preguntas / Posibles Mejoras

  • ¿Este enfoque (iterar sobre cada usuario y actualizar su título) corre el riesgo de problemas de rendimiento si hay muchos usuarios? ¿Existe una mejor práctica para esto?
  • ¿Algún consejo sobre optimización, ya sea para el trabajo programado o para la interfaz de usuario de configuración de administración?
  • ¿Hay algo inseguro o problemático en mi método con lo que deba tener cuidado?

¡Muchas gracias por tu gran trabajo y por este útil plugin!
Si tienes alguna sugerencia, o si planeas mejorar la configuración de títulos de grupo + nivel de confianza en el futuro, me encantaría escuchar tus ideas.

2 Me gusta

@joo ¡Idea realmente genial!

Si miras el plugin ahora, creo que yo también hice esto (estaba ejecutando algunas pruebas finales). Veo que recorriste cada usuario, pero en foros grandes, esto puede llevar tiempo.

Entonces, hice una ACTUALIZACIÓN SQL:

(Adapté la consulta de Ask Discourse y la modifiqué)

De esta manera, en la configuración tl1_title_on_promotion, deberías poder usar algo como Junior {group_name}, para que el título se convierta en Junior Developer.

Ten en cuenta que también tendrías que marcar add_primary_group_title para que funcione.

1 me gusta

Gracias por la explicación, ahora entiendo cómo funciona tu plantilla {group_name}.

Pero esto es exactamente a lo que me refería con la diferencia en la lógica. Mi requisito principal es poder aplicar estructuras de títulos completamente diferentes para el mismo nivel de confianza, basándome en diferentes grupos de usuarios.

Por ejemplo, para el Nivel de Confianza 3:

  • El título para el grupo “Diseñadores” debería ser “Diseñador Senior”.
  • El título para el grupo “Desarrolladores” debería ser “Líder Técnico”.

Estos dos títulos tienen estructuras completamente diferentes.

Intenté implementar esta característica con una IA, pero no tuve éxito. Me preguntaba si sería posible que modificaras el plugin para soportar esta lógica más granular.

Ah, creo que te entendí mal entonces.

¿Funcionó tu código anterior?

No, el código anterior que probé con una IA tampoco funcionó. Después de configurarlo todo, no pasó nada en absoluto.

Quería mostrarte el código completo de mi último intento. Esperaba que pudieras ver qué estoy haciendo mal.

1. plugin.rb

# name: add-title-by-group-trust-level
# about: asignar títulos por grupo principal + nivel de confianza usando SQL
# version: 0.2
# authors: tu-nombre

# Nota: No estoy seguro si necesito una línea 'require' aquí para cargar el archivo del trabajo.
# Sospecho que esta podría ser la pieza 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

Así es como lo configuré en la Configuración del Sitio:

Pegué este JSON en la configuración group_trust_level_titles:

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

El Problema:

El trabajo UpdateTitles no aparece en el programador de Sidekiq (/sidekiq/scheduler).

Sin embargo, lo probé en la consola de Rails según el método que me dio la IA, y la lógica principal está perfectamente bien, imprimiendo correctamente todos los usuarios que cumplen las condiciones.

Este es el script de prueba que usé en la consola de 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 "No se pudo encontrar el 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} Nivel de Confianza: #{tl} Nuevo Título: '#{title}' ======"
    users.each do |user|
      puts "Usuario id:#{user.id}, nombre de usuario:#{user.username}, título actual:'#{user.title}'"
    end
  end
end

Así que parece que la lógica en sí es correcta, pero Discourse no está registrando el trabajo programado. De todos modos, cuanto más intento cambiarlo, más confuso se vuelve… No estoy seguro de si este es el enfoque correcto, y como no sé codificar, se siente muy difícil de implementar. ¿Tienes un método mejor?

Hmm… tal vez quieras usar la configuración de objetos:

Con campos como Nivel de confianza, grupo, título.

1 me gusta

Solo quería dar una actualización y agradecer a todos los que ayudaron.

¡Con los últimos cambios, el plugin ahora funciona exactamente como pretendía! Asigna correctamente diferentes títulos según el grupo principal y el nivel de confianza del usuario.

A continuación, publico el código de trabajo final. Parece correcto, pero como no soy desarrollador, me preguntaba si hay alguna área de mejora u optimización que podría haber pasado por alto.

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

      # Obtener el valor de la configuración, que ahora es una cadena JSON
      rules_json_string = SiteSetting.group_based_title_rules
      return if rules_json_string.blank?

      begin
        # Esta es la corrección más crucial: analizar manualmente la cadena JSON en una matriz Ruby
        rules = JSON.parse(rules_json_string)
      rescue JSON::ParserError
        # Si el formato JSON es incorrecto, salir directamente para evitar que la tarea falle
        Rails.logger.error("Plugin Títulos Basados en Grupo: Error al analizar 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

  # ESTO DEBE ser type: objects. Esta fue la fuente del error.
  group_based_title_rules:
    type: objects
    default: []
    schema:
      properties:
        group_id:
          type: integer
          name: "Grupo de Usuario"
          component: "group-chooser"
        trust_level:
          type: integer
          name: "Nivel de Confianza"
          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: Asigna títulos basados en el grupo principal y el nivel de confianza.
# version: 2.1.0
# authors: Tu Nombre

enabled_site_setting :add_title_by_group_trust_enabled

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