api.modifyClass a veces(!) no funciona

Editar: reclasificado como error.
Reproducción completa abajo.

Estoy usando api.modifyClass en un componente de tema.

En la mayoría de las páginas, esto funciona bien, pero en algunos temas, la propiedad no se agrega al modelo de usuario cuando se recarga la página. No puedo encontrar por qué funciona en la mayoría de los temas, pero no en algunos, o qué tienen en común los temas donde no funciona.
¿Alguien entiende qué estoy haciendo mal aquí?

Resumen: Agregar api.container.lookup para el modelo, debajo de modifyClass, soluciona este problema.

1 me gusta

¡Dios mío! ¡Creo que sé!

Creo que necesitas añadir un pluginId

     <script type="text/discourse-plugin" version="0.1">
    api.modifyClass('model:user', {
      pluginId: 'my-plugin', 
      testProperty: function() {
        return 1;
      } 
    });
    </script>

Es necesario en versiones posteriores, de hecho, envié PRs para un par de temas ayer para añadir esto. Quizás por fin me estoy convirtiendo en un desarrollador de plugins/temas.

2 Me gusta

¡Gracias, Jay! Eso realmente marcó la diferencia en mi instancia de prueba.
Pero desafortunadamente, no es una solución mágica, el problema todavía está ahí :frowning:

1 me gusta

Sí, creo que el pluginId está ahí para evitar que las modificaciones se apliquen dos veces. ¿La falta de este no debería explicar por qué no se ha ejecutado ni una vez?

1 me gusta

Maldición. Justo cuando pensaba que sabía algo. :crying_cat_face:

Pensé que tal vez si algo más estaba modificando la clase, podría ser una condición de carrera para ver cuál lo hacía. Pero JavaScript sigue siendo en su mayor parte un misterio para mí.

2 Me gusta

Sigue siendo un problema con el código, por lo que es razonable plantearlo.

1 me gusta

Sí, eso también se me pasó por la cabeza. Pero esto todavía falla en un sitio de prueba con este como el único componente temático.

1 me gusta

Por cierto, si agregas esto a un Componente de Tema en, por ejemplo:

  • /javascripts/discourse/initializers/test-init.js.es6

¿cambia/mejora el comportamiento?

No estoy seguro de si estas cosas son semánticamente idénticas…

… teóricamente, ambas deberían evaluarse cuando el navegador se actualiza, después de lo cual una condición de carrera debería ser irrelevante en la transición de ruta, ya que la modificación ya debería haberse aplicado…

1 me gusta

No, el mismo comportamiento.

Creé un componente temático con javascripts/discourse-test/initializers/initialize-discourse-test.js.es6:

import { withPluginApi } from "discourse/lib/plugin-api";

export default {
  name: 'discourse-test-initializer',
  initialize(){
    console.log('here1');
    withPluginApi("0.1", api => {
      console.log('here2');

      api.modifyClass('model:user', {
        pluginId: 'test',
        testFunction: function() {
          console.log('here3');
          return 2;
        }
      });

    });
  }
}

Imprime

here1
here2

en cada página.

En algunos temas, al ingresar Discourse.currentUser.testFunction() en la consola funciona y produce here3 y 2 como salida.

En algunos temas no funciona (Uncaught TypeError: Discourse.currentUser.testFunction is not a function)

2 Me gusta

Ok, vi una notificación de una publicación útil que aparentemente ha sido eliminada mientras tanto.
La sugerencia no funcionó, pero contenía una pista que me ayudó a resolver esto.

Agregar el siguiente fragmento debajo del código que no funciona resolvió consistentemente los problemas que estaba teniendo. He probado esto en múltiples foros independientes, tanto en estable como en tests-passed. Creo que esto debería ser reclasificado como Bug

<script type="text/discourse-plugin" version="0.1">
const userModel = api.container.lookup("model:user");
</script>

@Johani ¡gracias por tu ayuda!

2 Me gusta

Reclasificando esto como un error.

He añadido un console.log en el código de la API del plugin app/assets/javascripts/discourse/app/lib/plugin-api.js para que registre cada vez que se llama a modifyClass.

He eliminado todos los plugins externos para asegurarme de que no hubiera ningún conflicto.

Reproducción:

  • Crea un foro vacío en stable (sin Ember CLI). Esto tampoco funciona en tests-passed (sin Ember CLI). No lo he probado con Ember CLI.

  • Añade un componente de tema con esto en Común - Cabecera

#1 Funciona


    api.modifyClass('model:user', {
      pluginId: 'test-tc',
      testFunction: function() {
        return 1;
      }
    });

  • Carga la página de inicio

  • La consola muestra modifyClass called for model:user _application-08d9058ddd37ba80992f770509f4919ad0738a17f14fb85167b1dc1f32f8b56e.js:23490:16 Object { pluginId: "test-tc", testFunction: testFunction() }

  • Introduce Discourse.currentUser.testFunction() en la consola

  • Se imprime “1”

#2 Falla

  • Ve a un tema, por ejemplo ‘Welcome to Discourse’ y recarga la página
  • La consola muestra los mismos logs de “modifyClass called”
  • Introduce Discourse.currentUser.testFunction() en la consola
  • Se imprime Uncaught TypeError: Discourse.currentUser.testFunction is not a function

#3 Falla con advertencia

  • Añade una sola línea al principio del componente de tema para que se vea así:

    const userModel = api.container.lookup("model:user");

    api.modifyClass('model:user', {
      pluginId: 'test-tc',
      testFunction: function() {
        return 1;
      }
    });

  • Ve a un tema, por ejemplo ‘Welcome to Discourse’ y recarga la página
  • La consola muestra los mismos logs de “modifyClass called”
  • La consola muestra una advertencia "model:user" was already cached in the container. Changes won't be applied.
  • Introduce Discourse.currentUser.testFunction() en la consola
  • Se imprime Uncaught TypeError: Discourse.currentUser.testFunction is not a function

#4 Funciona

  • Mueve la línea de lookup al final del componente de tema para que se vea así:

    api.modifyClass('model:user', {
      pluginId: 'test-tc',
      testFunction: function() {
        return 1;
      }
    });

    const userModel = api.container.lookup("model:user");

  • Ve a un tema, por ejemplo ‘Welcome to Discourse’ y recarga la página
  • La consola muestra los mismos logs de “modifyClass called”
  • Introduce Discourse.currentUser.testFunction() en la consola
  • Se imprime “1” :partying_face:
4 Me gusta

Revisando esto:

En Discourse 2.8 y versiones posteriores, al usar Discourse.User.current().testFunction(), el caso n.º 2 sigue fallando.

1 me gusta

Tengo un problema con modifyClass también, ¿no estoy seguro si está relacionado?: Issues overriding getters in a controller (3.0.0)

Acabo de mejorar nuestra advertencia para este tipo de situación:

y también he redactado esta documentación que explica la causa y cómo resolverla:

Creo que eso debería solucionar todas las preocupaciones de este tema. Si no es así, por favor comparte algún ejemplo de código fallido y lo revisaré.

11 Me gusta

Este tema se cerró automáticamente después de 3 días. Ya no se permiten nuevas respuestas.