rouvrirWidget avec appel AJAX

C’est un sujet qui est apparu plusieurs fois et qui a stagné (généralement parce que le développeur n’a pas réellement besoin de l’appel AJAX). Cependant, je développe un plugin qui accède à des données qui ne sont pas stockées dans la base de données de Discourse (bot Discord autonome) et j’essaie d’utiliser ces données pour décorer des publications.

export default Component.extend({
  init() {
    this._super(...arguments);

    var self = this;
    const store = getOwner(this).lookup("service:store");

      let positions = [];

    store
      .findAll("position", {
        ...args,
      })
      .then((data) => {

        for (const [key, position] of Object.entries(data.content)) {
          positions.pushObject(EmberObject.create({ ...position }));
        }
      });

    withPluginApi("1.4.0", (api) => {
      api.reopenWidget("post", {
        html(attrs) {
          let position = positions.filter(
            (position) => position.user.id == attrs.user.id
          );

          if (position.length > 0) {
            attrs.cooked = "Has Position";
          }

          return this.attach("post-article", attrs);
        },
      });
    });
  },
});

J’ai essayé différentes variations de ce code, y compris l’appel de fonction api dans la partie .then de la requête store et ainsi de suite, et elles aboutissent toutes au même résultat, à savoir que les modifications apportées aux publications ne sont pas rendues tant que vous ne faites pas défiler.

Toutes ces tentatives ont été faites tard le soir, il est donc très probable que je manque quelque chose de très évident, mais toute aide serait grandement appréciée.

Cela dépend de ce que vous essayez de faire, je suppose, mais pourquoi ne pas utiliser l’API Ruby officielle de Discord pour obtenir les données dans la base de données Discourse, les sérialiser vers le client, puis les utiliser dans le widget ?

Cela semblait être une complexité inutile alors que l’API des applications principales est suffisamment bonne pour la plupart des choses, mais je pourrais mal comprendre l’implémentation car je devrai admettre que j’aurai besoin d’étudier un peu plus le côté Ruby de Discourse.

Cependant, si je ne parviens pas à faire fonctionner la décoration de publication, je devrai probablement passer par là.

Pour revenir vous remercier @merefield, j’ai approfondi la sérialisation et j’ai pu accomplir la tâche en effectuant l’appel API dans le sérialiseur au lieu de le demander depuis JS comme je le faisais.

Je suis sûr qu’il y a une pléthore de raisons pour lesquelles ce n’est pas suggéré, mais cela fonctionne pour moi, donc je continue avec ça. Pour ceux qui trouveront cela à l’avenir, vous pouvez insérer des données dans un sérialiseur avec le code suivant :

add_to_serializer(:topic_view, :data_name) do
    JSON.parse(Net::HTTP.get(URI('https://yourwebsite.com?topic_id=' + object.topic.id.to_s)))
end

Ce qui vous permet ensuite d’accéder aux données lors d’un appel à reopenWidget. Dans mon cas, j’ajoute les données pertinentes au sujet au sérialiseur topic_view et j’y accède tout en modifiant le post comme ceci :

api.reopenWidget("post", {
          html(attrs) {
            let data_name = this.model.topic.data_name;

            // Faire des choses avec les données

            return this.attach("post-article", attrs);
          },
        });

Comme je l’ai dit précédemment, il y a probablement une tonne de raisons pour lesquelles ce n’est pas la bonne façon de faire, mais cela fonctionne pour mon cas d’utilisation avec un impact minimal sur les temps de chargement.

Pour ceux qui cherchent à accomplir la tâche dans JS pour quelque raison que ce soit, le code pertinent semble exister dans le plugin discourse-encrypt où ils décryptent les posts, mais j’ai trouvé cette méthode beaucoup plus facile à implémenter : discourse-encrypt/assets/javascripts/discourse/initializers/decrypt-posts.js at 255724ebc5fc3956f26beca09c1f7cb273d76eb2 · discourse/discourse-encrypt · GitHub

Étrangement, cela semble casser le composant thématique Topic Thumbnails en rendant les images surdimensionnées GitHub - discourse/discourse-topic-thumbnails: Display thumbnails in topic lists

Vraiment une interaction étrange, rien d’autre de notable cependant.

Hmmm… Je ne suis pas sûr que ce soit architecturalement sain. Bien qu’il soit formidable que vous exploriez une solution back-end (les appels de serveur à distance devraient presque toujours se faire entre les processus du back-end, surtout lorsqu’il s’agit d’authentification et d’autorisation), les données devraient sans doute se charger de manière asynchrone, et le sérialiseur ne devrait pas dépendre de la fin d’un appel distant pour conclure. Au minimum, vous devriez encapsuler cet appel dans un cache ?

Voyez comment vous vous en sortez, mais faites particulièrement attention au moment du chargement de la page avant et après ce changement, vous pourriez introduire un délai important.

En pratique, cela ajoute entre 10 et 50 ms par chargement, tout au plus. La connexion a une latence très faible car les deux boîtes se trouvent dans le même centre de données. En fait, la méthode que j’utilise pour intégrer des données dans les composants charge les pages marginalement plus rapidement que Discourse ne rend ses propres pages statiques (différence d’environ 100 ms), et cela inclut une opération de base de données qui utilise les identifiants Discord pour ajouter des données utilisateur aux réponses de l’API avant qu’elles ne soient transmises au client. (Ruby demande des données à une application externe → Analyse JSON → Boucle each de requête de base de données pour ajouter des données à la réponse → Génération de JSON et retour au client frontend). C’est compréhensible compte tenu de la taille de la base de code, mais il y a certainement une surcharge interne qui laisse de la place pour que ces requêtes, traditionnellement considérées comme « coûteuses », passent complètement inaperçues. Cela dit, nous parlons ici de la vitesse de la lumière et du son, ce qui, pour l’utilisateur final, reste incroyablement rapide car Discourse est une plateforme incroyable.

Un cache serait un excellent ajout et je vais me pencher dessus, je suis très nouveau dans Ruby, donc je mettrai à jour au fur et à mesure que j’en apprendrai davantage sur les fonctions disponibles. Je vais mettre cela à jour au fur et à mesure, car je pense qu’une sorte de méthode pour cela, bien qu’un peu bancale pour le moment, pourrait être potentiellement très bénéfique pour le développement de plugins. Pour les personnes ayant des applications existantes, pouvoir utiliser l’API qu’elles connaissent pour faire glisser les données dont elles ont besoin là où elles en ont besoin efficacement, sans avoir à construire des systèmes pour synchroniser les données entre leur base de données et Discourse ou à se soucier de modèles supplémentaires ou de migrations de base de données, réduit considérablement le temps de développement et maintient les auteurs de plugins dans certains des domaines les mieux documentés de l’application (c’est-à-dire l’API des plugins).

J’apprécie grandement cet éclairage, je suis vraiment impatient de continuer à en apprendre davantage sur cette plateforme et, espérons-le, d’y contribuer à l’avenir.

3 « J'aime »

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.