Anular user_guardian.rb en un plugin (¡no es necesario hacer fork!)

Hola, disculpen la pregunta de principiante. He estado leyendo la documentación, pero necesito una guía, por favor.

He bifurcado Discourse y realizado mis propios cambios, y me gustaría hacer mi propia implementación a partir de ellos. La guía de contribución explica cómo hacer cambios y enviar un PR, pero en este caso no quiero hacer un PR. Solo me gustaría tomar mi pequeño cambio y lograr que una instalación de Discourse funcione con ello. Pensé que la forma de hacerlo era cambiar esta línea para que apunte a mi propio repositorio:

Lo hice e hice una instalación, pero los cambios que realicé no se están mostrando, así que claramente estoy haciendo algo mal. ¿Alguna idea? ¡Gracias!

EDIT:
Por transparencia, y en caso de que alguien tenga una forma más sencilla de hacerlo, todo lo que intento hacer es permitir que los usuarios anónimos cambien sus nombres de usuario cuando entran en modo anónimo. Es tan simple como cambiar false por true en esta línea:

Si hay una mejor manera, estoy todo oídos. Pero esto es todo lo que necesito habilitar. Tengo experiencia con Python, Java y muchas otras cosas de back end, pero no sé nada de Ruby/JavaScript/HTML/etc.

EDIT2:
Según una publicación que vi en otro lugar, actualicé app.yml de la siguiente manera:

run:
- exec:
 cd: /var/www/discourse
 cmd:
    - sudo -u discourse git remote set-url origin https://github.com/my/forked/discourse.git
    - sudo -u discourse git fetch origin
    - sudo -u discourse git checkout origin/master

Aún no hay resultados después de reconstruir la aplicación. Se inicia correctamente, pero parece que mis cambios no están presentes.

¿No es posible encapsular tus cambios en un plugin y usar ese en su lugar?

5 Me gusta

Todos los que han hecho eso se han arrepentido mucho. Y aquí no podrás obtener mucha ayuda.

Hagas lo que hagas, hazlo en un plugin.

10 Me gusta

De acuerdo. ¿Tienes alguna idea de cómo podría hacer esto mediante un complemento?

Hola @leighno5

Mis pensamientos para ti, basados en mi experiencia personal, son que escribir plugins en Ruby para lograr lo que estás haciendo en tu “fork” es mucho más fácil hacerlo mediante un plugin, siempre y cuando entendamos Ruby y Rails lo suficiente como para escribir fácilmente un plugin para Discourse (o modificar cualquier clase de Rails).

Si no entendemos Rails y Ruby lo suficientemente bien como para escribir un plugin de Discourse, mi experiencia es que bifurcar Discourse y hacer modificaciones en el núcleo es un camino “equivocado”.

Supongo que la analogía sería esta (perdona por esta idea tan sencilla):

“Alguien encuentra difícil caminar; así que decide correr en su lugar.”

Déjame explicarlo, si no te importa:

Antes de empezar a escribir aplicaciones en Rails (nada que ver con Discourse) y de intentar escribir plugins para Discourse, me sentía un poco perdido; incluso creo que estaba un poco molesto con Discourse. Es como cuando quieres golpear una pelota de golf por primera vez; no va en línea recta y requiere mucho trabajo para que la pelota caiga en el medio del fairway. Bifurcar Discourse es como sacar el driver grande en el campo de práctica antes de saber hacer chips y putts con los hierros cortos.

Tomé un descanso de las modificaciones en el núcleo de Discourse (hace muchos meses) y trabajé un tiempo construyendo varias aplicaciones de Rails desde cero; y entonces (y solo entonces) empecé a desarrollar un conocimiento “instintivo” sobre Rails. Después de eso, cuando decidí modificar Discourse (actualmente ejecuto 6 plugins personalizados que escribí en producción para Discourse), todo se volvió intuitivo y los plugins que modificaban el núcleo de Ruby se volvieron demasiado simples.

Ruby es muy flexible. Podemos sobrescribir cualquier clase, cualquier objeto. Podemos redefinir cada aspecto de Ruby. Con algo de experiencia, empezamos a pensar: “¡WOW!, no sabía que Ruby era tan flexible (y poderoso)” y empezamos a “volvernos peligrosos” porque podemos volar como Superman con Ruby y Rails. En ese momento, estamos al principio de nuestro viaje con Ruby y Rails, ¡no al final!

Con el conocimiento de Ruby y Rails que he adquirido en 2020, sabiendo lo que sé ahora, nunca bifurcaría Discourse y haría cambios en el núcleo de Ruby y Rails como estás proponiendo, porque los plugins son simplemente demasiado fáciles para sobrescribir y modificar las clases de Ruby, cuando entendemos los fundamentos de las clases de Ruby y los conceptos básicos de la metaprogramación.

Creo que lo que estoy diciendo, disculpa ser tan directo, es que si alguien piensa que necesita modificar el núcleo de Discourse para hacer algunos cambios menores en Ruby, entonces no entiende Ruby y Rails lo suficiente; porque si lo hiciera, no modificaría el núcleo y simplemente escribiría un plugin rápido para sobrescribir las clases y disfrutaría del monkey-patching.

Por otro lado, si quisiera hacer algo loco y ser infeliz, como reemplazar EmberJS de Discourse por React y Ant Design, ¡entonces bifurcar sería la única opción! Sin embargo, en mi opinión, “Discourse” no está definido por las “librerías de Javascript”. Discourse está definido por las habilidades del equipo de desarrollo principal (las personas) y su atención al detalle, servicio al cliente, enfoque de equipo en el desarrollo de código de código abierto, su pipeline de características SPA, y todo su arduo trabajo. Sería un poco loco (en mi mente) desechar todo ese poder intelectual solo porque quizás nos guste más Ant Design (con React) o VueJS que Ember.

Esto es igualmente cierto, e incluso más, si solo vamos a modificar el núcleo de Discourse aquí y allá. Sería un poco “locura” bifurcarlo para hacer eso, desechar a las “personas” que son el “verdadero” Discourse (no el código).

Solo hablo desde mi viaje personal en 2020 aprendiendo Ruby y Rails. Ahora, lo básico se está volviendo fácil y me estoy volviendo “peligroso”, LOL. Puedo “hacer monkey-patching con cualquier cosa”, lo cual no siempre es bueno; y para eso están los plugins de Discourse.

Mantén el núcleo sólido como una roca y disfruta “jugando” con Discourse mediante plugins.

Espero que esto ayude.

Nota: mientras escribía esta respuesta, tú escribiste:

Esto de alguna manera confirma mi punto, ¿no crees?

Escribir un “plugin” en Discourse es escribir “código Ruby” (en un nivel) y para otros va mucho más profundo (en EmberJS).

Antes de empezar a escribir plugins para Discourse, mi consejo amigable, aunque quizás parezca sin valor para ti, es que primero desarrolles algunas aplicaciones de Ruby on Rails. Aprende a moverte por Ruby y Rails, al menos lo básico; después de eso, habrás respondido tu propia pregunta anterior.

Esta mañana estuve en una llamada de conferencia con un cliente durante tres horas revisando una aplicación de Rails, validaciones, modelos, etc., y luego, mientras tomaba un descanso después de codificar algunas de las acciones derivadas de la llamada, leí tu publicación.

En mi opinión, el camino más corto para escribir plugins de Discourse es aprender Rails primero.

¡Espero que esto ayude!

5 Me gusta

Aquí tienes un buen punto de partida:

3 Me gusta

No, tienes toda la razón. No tengo ninguna experiencia con Ruby, así que, por supuesto, no me ofendo en lo más mínimo.

He leído la guía del complemento y la he revisado un par de veces, pero lamentablemente mi desconocimiento de Ruby sigue siendo frustrante, y no tengo la menor idea de cómo escribiría un complemento que sobrescriba ese pequeño fragmento de código en el archivo user-guardian para permitir que los usuarios anónimos cambien sus nombres. :confused:

2 Me gusta

Hola @leighno5

Sí, te entiendo.

Esos temas de complementos tipo “CÓMO HACERLO” fueron escritos por desarrolladores muy talentosos con más de una década de experiencia programando en Rails y Ruby (quizás incluso más). De hecho, algunos de esos chicos están entre los mejores desarrolladores de Ruby y JS del mundo.

Estoy 100% seguro de que todos esos chicos aprendieron Rails y Ruby mucho antes de escribir su primer complemento para Discourse.

En realidad, no es tan difícil aprender Rails; pero necesitas realizar realmente el “rito práctico” de construir algunas aplicaciones de Rails desde cero. No solo seguir un tutorial de YouTube (lo cual es bueno), sino construir una aplicación funcional donde debas encargarte de configurar la base de datos, generar tus propios modelos, crear tus propios controladores, escribir validaciones de modelos, redactar inicializadores, módulos de ayuda, realizar migraciones (modificaciones) de la BD, trabajar con Ruby embebido y más.

Es realmente muy divertido y es el “camino más corto” para aprender a sentirte cómodo escribiendo complementos (en lo que respecta al lado de Rails; personalmente no trabajo mucho con Ember, pero me encanta el lado de Rails).

Además, ¡debes aprender a usar la consola de Rails! La consola de Rails es realmente divertida y la uso a diario con mucho gusto.

Hoy, mi cliente favorito y yo estábamos usando AnyDesk y me preguntó: “¿Podemos tener esta nueva vista del Inventario?”. Él quería verme hacerlo todo. Después de que lo pusimos en marcha, al final de la llamada me dijo: “Hiciste algo en Rails en 30 minutos que hubiera tomado muchas semanas hace unas décadas”. ¡Realmente impresionante, @leighno5. ¡Adelante!

Después de aprender Rails, dirás: “¡GUÁO!” escribir complementos para Discourse es bastante fácil, al menos en lo que respecta a la parte de Rails y Ruby.

Espero que esto te ayude.

3 Me gusta

Mira el código de los #plugin existentes. Ahora hay absolutamente muchos, así que hay muchos ejemplos. No te saltes la lectura de lo que ya se ha hecho para poder aprovecharlo.

Parece que solo quieres sobrescribir un método, lo cual es simplemente un caso de redefinirlo en tu plugin.rb (aunque la mejor práctica es, sin duda, separarlo en su propio archivo por módulo, pero no vale la pena para un solo método).

5 Me gusta

Arriesgándome a demostrar aún más mi ignorancia y aprovechando la amabilidad que ya me has mostrado, ¿estarías dispuesto a ampliar un poco esto? O si conoces otro ejemplo donde alguien haya sobrescrito un módulo y puedas enlazarlo, te lo agradecería. No me opongo en absoluto a “leer el manual” (RTFM), pero mi falta de comprensión de cómo funciona Discourse es frustrante, a pesar de todo el tiempo que he dedicado a revisar varios tutoriales y documentos. Y sí, sé que preguntas tan básicas pueden hacer parecer que he puesto poco esfuerzo, ¡pero te prometo que no es así!

3 Me gusta

Aquí hay un ejemplo donde hemos definido un método en el PostGuardian:

Podrías hacer algo similar para el UserGuardian utilizando el nombre del método existente, lo cual debería sobrescribirlo.

Solución simple (para que funcione, aunque no sea robusta):

Simplemente escribe el código original del método y realiza tu edición. Desventaja: si Discourse cambia el código, tu plugin podría romper la instancia.

Solución avanzada (más robusta):

Para obtener puntos extra, podrías usar super para heredar el método original, aunque no está garantizado que funcione por razones que no detallaré aquí. Sin embargo, es la mejor práctica, ya que las actualizaciones de ese método en Discourse siempre se tendrán en cuenta sin que tengas que editar tu plugin.

Discourse es una plataforma. Requiere tiempo para aprenderla. Ve paso a paso.

6 Me gusta

Esto es lo que me preocupaba. ¿El método avanzado mencionado en tu siguiente párrafo está cubierto en la guía paso a paso? ¿Existe un buen ejemplo simple de su uso en un plugin existente que pueda ser utilizado (copiado) para crear un nuevo plugin?

No te preocupes por el método avanzado por ahora. Solo haz que funcione. Puedes investigar Ruby on Rails en general en otras partes de las guías en línea. Es un poco fuera del alcance de Discourse específicamente y de este foro. Tenlo en cuenta.

1 me gusta

¡Vale, gracias! Digamos que me pongo a escribir un plugin breve. Si lo he entendido bien, debería revisar el código principal en cada actualización y reescribir el plugin si ha cambiado el código relevante del núcleo. ¿Es eso? Gracias.

1 me gusta

Eso es correcto. Solo revísalo ocasionalmente y especialmente si comienza a fallar. El código de Guardian es un poco más crítico, ya que se trata de la autorización del sitio de codificación, así que manténlo bajo supervisión.

Otra solución es agregar casos de prueba (también conocidos como especificaciones) y configurar un trabajo automatizado para ejecutarlos… ¡pero eso se vuelve complicado!

2 Me gusta

Otra tarea de crédito extra es configurar travis-ci.org para ejecutar las pruebas de tu plugin, de modo que recibas una notificación si algo falla.

5 Me gusta

Claramente, no es una tarea que deba tomarse a la ligera. Me gustaría modificar los modales de inicio de sesión/crear nueva cuenta y eliminar la imagen de Twitter. Quizás este último sería un mejor primer proyecto. Gracias.

Si alguien se encuentra con esto y estaba tan perdido como yo, comparto mi código a continuación, ya que logré que funcionara como se pretendía. No modifiqué ningún archivo. Simplemente creé un nuevo archivo plugin.rb y coloqué lo siguiente dentro:

# name: noms
# about: Permite a los usuarios en Modo Anónimo cambiar sus nombres de usuario
# version: 0.1


require_dependency 'guardian'
require_dependency 'guardian/user_guardian'

class ::Guardian
end

module ::UserGuardian
  def can_edit_username?(user)
    return false if SiteSetting.sso_overrides_username?
    return true if is_staff?
    return false if SiteSetting.username_change_period <= 0
    return true if is_anonymous?
    is_me?(user) && ((user.post_count + user.topic_count) == 0 || user.created_at > SiteSetting.username_change_period.days.ago)
  end


  def can_edit_name?(user)
    return false unless SiteSetting.enable_names?
    return false if SiteSetting.sso_overrides_name?
    return true if is_staff?
    return true if is_anonymous?
    can_edit?(user)
  end
end

Esto anula la clase user_guardian.rb en el núcleo de Discourse para permitir que los usuarios cambien el nombre de usuario y el nombre de sus cuentas de usuario anónimas.

Si comparas lo que tengo aquí con lo que hay en user_guardian.rb en el núcleo de Discourse, verás que hay un montón de otra cosa con la que no necesité hacer nada, así que la dejé intacta. Todo lo que necesitaba era editar esos dos métodos can_edit_username y can_edit_name cambiando algunos valores de retorno de false a true, y pude lograr lo que necesitaba.

Ciertamente, se podrían realizar mejoras y es probable que haya mejores prácticas que pude deducir leyendo los enlaces en este hilo y en otros lugares, pero si eres completamente nuevo en Ruby como yo y solo quieres modificar algo muy sencillo en el núcleo, este es un ejemplo minimalista y funcional de lo que necesitas hacer.

Muchas gracias a las personas en este hilo por su paciencia conmigo y por sus ánimos y ayuda. En especial a @merefield, quien realmente me ha ayudado en otro hilo en el pasado.

10 Me gusta

JAJA

Has recorrido un largo camino desde tu idea inicial de bifurcar todo Discourse y abandonar la rama principal para este tipo de tareas simples.

Buen trabajo :slight_smile:

4 Me gusta

¿Siguiiste todo el camino de Install Discourse on Ubuntu or Debian for Development o simplemente trabajaste en tu sitio de producción y esperaste lo mejor?