api.modifyClass às vezes(!) não funciona

Editar: Reclassificado como bug.
Reprodutível completo abaixo.

Estou usando api.modifyClass em um componente de tema.

Na maioria das páginas, isso está funcionando bem, mas em alguns tópicos a propriedade não é adicionada ao modelo do usuário quando a página é recarregada. Não consigo descobrir por que está funcionando na maioria dos tópicos, mas não está funcionando em alguns, ou o que os tópicos onde não está funcionando têm em comum.
Alguém entende o que estou fazendo de errado aqui?

Resumindo: Adicionar api.container.lookup para o modelo, abaixo do modifyClass, contorna esse problema.

1 curtida

Minha nossa. Eu acho que sei!

Acho que você precisa adicionar um pluginId

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

É obrigatório em versões posteriores, eu realmente enviei PRs para alguns temas ontem para adicionar isso. Talvez eu esteja me tornando um desenvolvedor de plugins/temas, finalmente.

2 curtidas

Obrigado, Jay! Isso realmente fez uma diferença na minha instância de teste.
Mas, infelizmente, não é uma solução mágica para tudo, o problema ainda está lá :frowning:

1 curtida

Sim, o pluginId está lá para evitar que modificações sejam aplicadas duas vezes, acredito. A falta dele não deveria explicar por que ele não foi executado uma vez?

1 curtida

Droga. Justo quando eu pensei que sabia alguma coisa. :crying_cat_face:

Eu pensei que talvez se algo mais estivesse modificando a classe, poderia ser uma condição de corrida para ver qual delas o fez. Mas o JavaScript ainda é um mistério para mim.

2 curtidas

Ainda é um problema com o código, então é razoável levantá-lo.

1 curtida

Sim, isso também me ocorreu. Mas isso ainda falha em um site de teste com este como o único componente de tema.

1 curtida

Por curiosidade, se você adicionar isso a um Componente de Tema em, digamos:

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

em vez disso, o comportamento muda/melhora?

Não tenho certeza se essas coisas são semanticamente idênticas…

… teoricamente, ambas devem ser avaliadas quando o navegador é atualizado, após o qual uma condição de corrida não deve ter mais importância na transição de rota, pois a modificação já deve ter sido aplicada…

1 curtida

Não, mesmo comportamento.

Criei um componente de tema com 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

em todas as páginas.

Em alguns tópicos, digitar Discourse.currentUser.testFunction() no console funciona e retorna here3 e 2 como saída.

Em alguns tópicos, não funciona (Uncaught TypeError: Discourse.currentUser.testFunction is not a function)

2 curtidas

Ok, vi uma notificação de uma postagem útil que aparentemente foi removida entretanto.
A sugestão não funcionou, mas continha uma pista que me ajudou a resolver isso.

Adicionar o seguinte trecho abaixo do código que não funciona resolveu consistentemente os problemas que eu estava tendo. Testei isso em vários fóruns independentes, tanto em estável quanto em testes-passados. Acho que isso deveria ser reclassificado como Bug

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

@Johani obrigado pela ajuda!

2 curtidas

Reclassificando isso como bug.

Adicionei um console.log no código da API do plugin app/assets/javascripts/discourse/app/lib/plugin-api.js para que ele registre sempre que modifyClass for chamado.

Removi todos os plugins externos para garantir que não houvesse conflito.

Reprodução:

  • Crie um fórum vazio em stable (sem Ember CLI). Isso também não funciona em tests-passed (sem Ember CLI). Não testei com Ember CLI.

  • Adicione um componente de tema com o seguinte em Common - Head

#1 Funcionando


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

  • Carregue a página inicial

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

  • Digite Discourse.currentUser.testFunction() no console

  • “1” é impresso

#2 Falhando

  • Vá para um tópico, por exemplo, ‘Welcome to Discourse’ e recarregue a página
  • O console mostra os mesmos logs de “modifyClass called”
  • Digite Discourse.currentUser.testFunction() no console
  • Uncaught TypeError: Discourse.currentUser.testFunction is not a function é impresso

#3 Falhando com aviso

  • Adicione uma única linha no topo do componente de tema para que ele fique assim:

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

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

  • Vá para um tópico, por exemplo, ‘Welcome to Discourse’ e recarregue a página
  • O console mostra os mesmos logs de “modifyClass called”
  • O console mostra um aviso \"model:user\" was already cached in the container. Changes won't be applied.
  • Digite Discourse.currentUser.testFunction() no console
  • Uncaught TypeError: Discourse.currentUser.testFunction is not a function é impresso

#4 Funcionando

  • Mova a linha de lookup para o final do componente de tema para que ele fique assim:

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

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

  • Vá para um tópico, por exemplo, ‘Welcome to Discourse’ e recarregue a página
  • O console mostra os mesmos logs de “modifyClass called”
  • Digite Discourse.currentUser.testFunction() no console
  • “1” é impresso :partying_face:
4 curtidas

Revisitando isto:

No Discourse 2.8 e superior, usando Discourse.User.current().testFunction(), o caso nº 2 ainda está falhando.

1 curtida

Estou tendo um problema com modifyClass também, não tenho certeza se está relacionado?: Issues overriding getters in a controller (3.0.0)

Acabei de melhorar nosso aviso para esse tipo de situação:

e também escrevi esta documentação que explica a causa e como resolvê-la:

Acho que isso deve resolver todas as preocupações neste tópico. Se não, por favor, compartilhe um exemplo de código com falha e eu darei uma olhada.

11 curtidas

Este tópico foi automaticamente fechado após 3 dias. Novas respostas não são mais permitidas.