api.modifyClass иногда (!) не работает

Edit: переклассифицировано как ошибка.
Полное воспроизведение ниже.

Я использую api.modifyClass в компоненте темы.

На большинстве страниц это работает нормально, но в некоторых темах свойство не добавляется к модели пользователя при перезагрузке страницы. Я не могу понять, почему это работает на большинстве тем, но не работает на некоторых, или что общего у тем, где это не работает.

Понимает ли кто-нибудь, что я делаю не так здесь?

TL;DR Добавление api.container.lookup для модели ниже modifyClass обходит эту проблему.

1 лайк

Ого, кажется, я знаю!

Думаю, вам нужно добавить pluginId:

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

В более новых версиях это обязательно. Вчера я даже отправил несколько PR для тем, чтобы добавить это поле. Похоже, я наконец-то становлюсь разработчиком плагинов и тем.

2 лайка

Спасибо, Джей! Это действительно помогло на моём тестовом экземпляре.
Но, к сожалению, это не универсальное решение — проблема всё ещё сохраняется :frowning:

1 лайк

Да, pluginId, я полагаю, нужен для предотвращения повторного применения модификаций. Отсутствие этого параметра не должно объяснять, почему модификация вообще не была выполнена ни разу?

1 лайк

Черт. Только что думал, что я что-то понимаю. :crying_cat_face:

Мне казалось, что если что-то ещё изменяет класс, то это может быть гонка, чтобы увидеть, кто это сделал. Но JavaScript для меня всё ещё в основном загадка.

2 лайка

Это всё ещё проблема в коде, поэтому её стоит поднять.

1 лайк

Да, это тоже пришло мне в голову. Но это всё равно не работает на тестовом сайте, где это единственный компонент темы.

1 лайк

Из любопытства, если вы добавите это в компонент темы, например:

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

изменится ли или улучшится ли поведение?

Не уверен, семантически ли эти вещи идентичны…

… теоретически оба варианта должны оцениваться при обновлении браузера, после чего гонка условий на переходе маршрута становится неактуальной, так как модификация уже должна быть применена…

1 лайк

Нет, поведение осталось прежним.

Я создал компонент темы с файлом 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;
        }
      });

    });
  }
}

На каждой странице выводится:

here1
here2

В некоторых темах выполнение Discourse.currentUser.testFunction() в консоли работает и выводит here3 и 2.

В других темах это не работает (Uncaught TypeError: Discourse.currentUser.testFunction is not a function).

2 лайка

Хорошо, я получил уведомление от полезного сообщения, которое, похоже, было удалено между тем.
Предложение не сработало, но оно содержало подсказку, которая помогла мне решить эту проблему.

Добавление следующего фрагмента ниже неработающего кода последовательно решало проблемы, с которыми я сталкивался. Я протестировал это на нескольких независимых форумах, как на стабильной версии, так и на версии с прошедшими тестами. Я думаю, что это следует переклассифицировать как Contribute > Bug

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

@Johani, спасибо за вашу помощь!

2 лайка

Переклассифицирую это как баг.

Я добавил console.log в код API плагинов app/assets/javascripts/discourse/app/lib/plugin-api.js, чтобы он выводил сообщение каждый раз, когда вызывается modifyClass.

Я удалил все внешние плагины, чтобы убедиться, что конфликта нигде нет.

Воспроизведение:

  • создайте пустой форум на ветке stable (без Ember CLI). Это также не работает на ветке tests-passed (без Ember CLI). Я не тестировал это с Ember CLI.

  • добавьте компонент темы со следующим кодом в раздел Common - Head

#1 Работает

<script type="text/discourse-plugin" version="0.1">
    api.modifyClass('model:user', {
      pluginId: 'test-tc',
      testFunction: function() {
        return 1;
      } 
    });
</script>
  • загрузите главную страницу

  • в консоли появится сообщение: modifyClass called for model:user _application-08d9058ddd37ba80992f770509f4919ad0738a17f14fb85167b1dc1f32f8b56e.js:23490:16 Object { pluginId: "test-tc", testFunction: testFunction() }

  • введите в консоли Discourse.currentUser.testFunction()

  • будет выведено значение 1

#2 Не работает

  • перейдите к любой теме, например, “Добро пожаловать в Discourse”, и обновите страницу
  • в консоли появятся те же логи с сообщением “modifyClass called”
  • введите в консоли Discourse.currentUser.testFunction()
  • будет выведено сообщение об ошибке: Uncaught TypeError: Discourse.currentUser.testFunction is not a function

#3 Не работает с предупреждением

  • добавьте одну строку в начало компонента темы, чтобы он выглядел так:
<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>
  • перейдите к любой теме, например, “Добро пожаловать в Discourse”, и обновите страницу
  • в консоли появятся те же логи с сообщением “modifyClass called”
  • в консоли появится предупреждение: "model:user" was already cached in the container. Changes won't be applied.
  • введите в консоли Discourse.currentUser.testFunction()
  • будет выведено сообщение об ошибке: Uncaught TypeError: Discourse.currentUser.testFunction is not a function

#4 Работает

  • переместите строку lookup в конец компонента темы, чтобы он выглядел так:
<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>
  • перейдите к любой теме, например, “Добро пожаловать в Discourse”, и обновите страницу
  • в консоли появятся те же логи с сообщением “modifyClass called”
  • введите в консоли Discourse.currentUser.testFunction()
  • будет выведено значение 1 :partying_face:
4 лайка

Возвращаясь к этому:

В Discourse 2.8 и выше при использовании Discourse.User.current().testFunction() случай №2 всё ещё не работает.

1 лайк

У меня тоже возникла проблема с modifyClass, не уверен, связана ли она с этим?: Issues overriding getters in a controller (3.0.0)

Я только что улучшил наше предупреждение для подобных ситуаций:

а также подготовил документацию, объясняющую причину проблемы и способы её решения:

Думаю, это должно устранить все вопросы, поднятые в этой теме. Если нет, пожалуйста, приведите пример кода, вызывающего ошибку, и я разберусь.

11 лайков

Эта тема была автоматически закрыта через 3 дня. Новые ответы больше не принимаются.