api.modifyClass a volte(!) non funziona

Modifica: riclassificato come bug.
Riproduzione completa qui sotto.

Sto usando api.modifyClass in un componente tema.

Sulla maggior parte delle pagine funziona bene, ma in alcuni argomenti la proprietà non viene aggiunta al modello utente quando la pagina viene ricaricata. Non riesco a capire perché funzioni sulla maggior parte degli argomenti, ma non su alcuni, o cosa abbiano in comune gli argomenti in cui non funziona.
Qualcuno capisce cosa sto sbagliando qui?

TL;DR Aggiungere api.container.lookup per il modello, sotto modifyClass, aggira questo problema.

1 Mi Piace

Oh mio Dio. Potrei saperlo!

Penso che tu debba aggiungere un pluginId

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

È richiesto nelle versioni successive, ho effettivamente inviato delle PR per un paio di temi ieri per aggiungere questo. Potrei finalmente diventare uno sviluppatore di plugin/temi.

2 Mi Piace

Grazie Jay! Ha effettivamente fatto la differenza sulla mia istanza di test.
Ma sfortunatamente non è una soluzione universale, il problema è ancora lì :frowning:

1 Mi Piace

Sì, il pluginId è lì per evitare che le modifiche vengano applicate due volte, credo. La sua mancanza non dovrebbe spiegare perché non è stato eseguito una volta?

1 Mi Piace

Accidenti. Proprio quando pensavo di sapere qualcosa. :crying_cat_face:

Pensavo che forse se qualcos’altro stesse modificando la classe, allora potrebbe esserci una race condition per vedere quale dei due lo facesse. Ma JavaScript è ancora per lo più un mistero per me.

2 Mi Piace

È ancora un problema con il codice, quindi è ragionevole sollevare la questione.

1 Mi Piace

Sì, mi è venuto in mente anche questo. Ma questo fallisce ancora su un sito di test con questo come unica componente del tema.

1 Mi Piace

Per curiosità, se inserissi questo in un componente del tema in, ad esempio:

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

il comportamento cambia/migliora?

Non sono sicuro se queste cose siano semanticamente identiche…

… teoricamente entrambe dovrebbero essere valutate quando il browser si aggiorna, dopodiché una race condition dovrebbe essere irrilevante alla transizione di rotta poiché la modifica dovrebbe essere già stata applicata…

1 Mi Piace

No, stesso comportamento.

Ho creato un componente tematico 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;
        }
      });

    });
  }
}

Stampa

here1
here2

su ogni pagina.

Su alcuni argomenti, inserire Discourse.currentUser.testFunction() nella console funziona e restituisce here3 e 2 come output.

Su alcuni argomenti non funziona (Uncaught TypeError: Discourse.currentUser.testFunction is not a function)

2 Mi Piace

Ok, ho visto una notifica da un post utile che apparentemente è stato rimosso nel frattempo.
Il suggerimento non ha funzionato ma conteneva un indizio che mi ha aiutato a risolvere questo problema.

Aggiungere il seguente snippet sotto il codice non funzionante ha risolto in modo coerente i problemi che stavo riscontrando. L’ho testato su più forum indipendenti, sia su versioni stabili che su test-passati. Penso che questo dovrebbe essere riclassificato come Bug

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

@Johani grazie per il tuo aiuto!

2 Mi Piace

Riclassificazione come bug.

Ho aggiunto un console.log nel codice dell’API del plugin app/assets/javascripts/discourse/app/lib/plugin-api.js in modo che registri ogni volta che modifyClass viene chiamato.

Ho rimosso tutti i plugin esterni per assicurarmi che non ci fosse un conflitto da qualche parte.

Riproduzione:

  • crea un forum vuoto su stable (quindi senza Ember CLI). Questo non funziona nemmeno su tests-passed (senza Ember CLI). Non l’ho testato con Ember CLI.

  • aggiungi un componente tema con questo in Common - Head

#1 Funzionante

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

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

  • inserisci Discourse.currentUser.testFunction() nella console

  • viene stampato “1”

#2 Fallimento

  • Vai a un argomento, ad esempio ‘Welcome to Discourse’ e ricarica la pagina
  • la console mostra gli stessi log di “modifyClass called”
  • inserisci Discourse.currentUser.testFunction() nella console
  • viene stampato Uncaught TypeError: Discourse.currentUser.testFunction is not a function

#3 Fallimento con avviso

  • Aggiungi una singola riga in cima al componente tema in modo che appaia così:
<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>
  • Vai a un argomento, ad esempio ‘Welcome to Discourse’ e ricarica la pagina
  • la console mostra gli stessi log di “modifyClass called”
  • la console mostra un avviso \"model:user\" was already cached in the container. Changes won't be applied.
  • inserisci Discourse.currentUser.testFunction() nella console
  • viene stampato Uncaught TypeError: Discourse.currentUser.testFunction is not a function

#4 Funzionante

  • Sposta la riga di lookup in fondo al componente tema in modo che appaia così:
<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>
  • Vai a un argomento, ad esempio ‘Welcome to Discourse’ e ricarica la pagina
  • la console mostra gli stessi log di “modifyClass called”
  • inserisci Discourse.currentUser.testFunction() nella console
  • viene stampato “1” :partying_face:
4 Mi Piace

Riesaminando questo:

Su Discourse 2.8 e versioni successive, utilizzando Discourse.User.current().testFunction() , il caso n. 2 continua a fallire.

1 Mi Piace

Ho un problema anche con modifyClass, non sono sicuro se sia correlato?: Issues overriding getters in a controller (3.0.0)

Ho appena migliorato il nostro avviso per questo tipo di situazione:

e ho anche scritto questa documentazione che spiega la causa e come risolverla:

Penso che questo dovrebbe risolvere tutte le preoccupazioni in questo argomento. In caso contrario, condividi del codice di esempio non funzionante e darò un’occhiata.

11 Mi Piace

Questo argomento è stato chiuso automaticamente dopo 3 giorni. Non sono più consentite nuove risposte.