api.modifyClass ne fonctionne parfois (!) pas

Modification : reclassé en bug.
Reproduction complète ci-dessous.

J’utilise api.modifyClass dans un composant de thème.
Sur la plupart des pages, cela fonctionne bien, mais dans certains sujets, la propriété n’est pas ajoutée au modèle utilisateur lors du rechargement de la page. Je ne trouve pas pourquoi cela fonctionne sur la plupart des sujets, mais pas sur certains, ni ce que les sujets où cela ne fonctionne pas ont en commun.
Quelqu’un comprend-il ce que je fais mal ici ?

TL;DR L’ajout de api.container.lookup pour le modèle, en dessous de modifyClass, contourne ce problème.

1 « J'aime »

Oh mon Dieu. Je crois savoir !

Je pense que vous devez ajouter un pluginId

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

C’est requis dans les versions ultérieures, j’ai d’ailleurs soumis des PR pour quelques thèmes hier afin d’ajouter cela. Je pourrais enfin me transformer en développeur de plugins/thèmes.

2 « J'aime »

Merci Jay ! Cela a effectivement fait une différence sur mon instance de test.
Mais malheureusement, ce n’est pas une solution miracle universelle, le problème est toujours là :frowning:

1 « J'aime »

Oui, le pluginId est là pour éviter que les modifications ne soient appliquées deux fois, je crois. Son absence ne devrait pas expliquer pourquoi il n’a pas été exécuté une seule fois ?

1 « J'aime »

Zut. Juste au moment où je pensais savoir quelque chose. :crying_cat_face:

Je pensais que si quelque chose d’autre modifiait la classe, cela pourrait être une condition de concurrence pour voir lequel le faisait. Mais JavaScript reste encore en grande partie un mystère pour moi.

2 « J'aime »

C’est toujours un problème avec le code, donc il est raisonnable de le soulever.

1 « J'aime »

Oui, cela m’a traversé l’esprit aussi. Mais cela échoue toujours sur un site de test avec ceci comme seule composante de thème.

1 « J'aime »

Pour information, si vous ajoutez ceci dans un composant de thème, par exemple :

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

le comportement change-t-il/s’améliore-t-il ?

Je ne suis pas sûr que ces choses soient sémantiquement identiques…

… théoriquement, les deux devraient être évalués lors du rafraîchissement du navigateur, après quoi une condition de concurrence ne devrait plus poser de problème lors de la transition de route, car la modification devrait déjà avoir été appliquée…

1 « J'aime »

Non, même comportement.

J’ai créé un composant de thème avec 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;
        }
      });

    });
  }
}

Affiche

here1
here2

sur chaque page.

Sur certains sujets, entrer Discourse.currentUser.testFunction() dans la console fonctionne et donne here3 et 2 comme sortie.

Sur certains sujets, cela ne fonctionne pas (Uncaught TypeError: Discourse.currentUser.testFunction is not a function)

2 « J'aime »

Ok, j’ai vu une notification d’un post utile qui a apparemment été supprimé entre-temps.
La suggestion n’a pas fonctionné, mais elle contenait un indice qui m’a aidé à résoudre ce problème.

L’ajout de l’extrait suivant sous le code non fonctionnel a résolu de manière constante les problèmes que je rencontrais. Je l’ai testé sur plusieurs forums indépendants, sur stable et sur tests-passed. Je pense que cela devrait être reclassé comme Bug

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

@Johani merci pour votre aide !

2 « J'aime »

Reclassification en tant que bug.

J’ai ajouté un console.log dans le code de l’API du plugin app/assets/javascripts/discourse/app/lib/plugin-api.js pour qu’il s’affiche chaque fois que modifyClass est appelé.

J’ai supprimé tous les plugins externes pour m’assurer qu’il n’y avait pas de conflit.

Reproduction :

  • Créez un forum vide sur stable (donc sans Ember CLI). Cela ne fonctionne pas non plus sur tests-passed (sans Ember CLI). Je n’ai pas testé avec Ember CLI.

  • Ajoutez un composant de thème avec ceci dans Commun - En-tête

#1 Fonctionne

<script type="text/discourse-plugin" version="0.1">
    api.modifyClass('model:user', {
      pluginId: 'test-tc',
      testFunction: function() {
        return 1;
      }
    });
</script>
  • Chargez la page d’accueil

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

  • Entrez Discourse.currentUser.testFunction() dans la console

  • “1” est affiché

#2 Échoue

  • Allez sur un sujet, par exemple ‘Welcome to Discourse’ et rechargez la page
  • La console affiche les mêmes logs “modifyClass called”
  • Entrez Discourse.currentUser.testFunction() dans la console
  • Uncaught TypeError: Discourse.currentUser.testFunction is not a function est affiché

#3 Échoue avec avertissement

  • Ajoutez une seule ligne en haut du composant de thème pour qu’il ressemble à ceci :
<script type="text/discourse-plugin" version="0.1">
    const userModel = api.container.lookup("model:user");

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

</script>
  • Allez sur un sujet, par exemple ‘Welcome to Discourse’ et rechargez la page
  • La console affiche les mêmes logs “modifyClass called”
  • La console affiche un avertissement "model:user" was already cached in the container. Changes won't be applied.
  • Entrez Discourse.currentUser.testFunction() dans la console
  • Uncaught TypeError: Discourse.currentUser.testFunction is not a function est affiché

#4 Fonctionne

  • Déplacez la ligne lookup en bas du composant de thème pour qu’il ressemble à ceci :
<script type="text/discourse-plugin" version="0.1">
    api.modifyClass('model:user', {
      pluginId: 'test-tc',
      testFunction: function() {
        return 1;
      }
    });

    const userModel = api.container.lookup("model:user");
</script>
  • Allez sur un sujet, par exemple ‘Welcome to Discourse’ et rechargez la page
  • La console affiche les mêmes logs “modifyClass called”
  • Entrez Discourse.currentUser.testFunction() dans la console
  • “1” est affiché :partying_face:
4 « J'aime »

Revisiter ceci :

Sur Discourse 2.8 et versions ultérieures, en utilisant Discourse.User.current().testFunction() , le cas n° 2 échoue toujours.

1 « J'aime »

J’ai aussi un problème avec modifyClass, je ne sais pas si c’est lié ? : Issues overriding getters in a controller (3.0.0)

J’ai juste amélioré notre avertissement pour ce genre de situation :

et j’ai également rédigé cette documentation qui explique la cause et comment la résoudre :

Je pense que cela devrait répondre à toutes les préoccupations soulevées dans ce sujet. Sinon, veuillez partager un exemple de code défaillant et je l’examinerai.

11 « J'aime »

Ce sujet a été automatiquement fermé après 3 jours. Les nouvelles réponses ne sont plus autorisées.