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 desde então.
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 funcionava resolveu consistentemente os problemas que eu estava enfrentando. Testei isso em vários fóruns independentes, tanto na versão estável quanto na de testes aprovados. Acredito que isso deveria ser reclassificado como Contribute > Bug

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

@Johani, obrigado pela sua 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.