AJAX呼び出しでreopenWidgetを再オープン

これは何度か話題に上がり、行き詰まったトピックです(通常は開発者が実際に AJAX 呼び出しを必要としないため)。しかし、私は Discourse のデータベースに格納されていないデータ(自己完結型の Discord ボット)にアクセスするプラグインを開発しており、そのデータを使用して投稿を装飾しようとしています。

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);
        },
      });
    });
  },
});

このコードのさまざまなバリエーションを試しましたが、ストアクエリの .then 部分に関数呼び出しを含めるなど、すべて同じ結果になりました。投稿への変更が表示されるのは、スクロールするまで表示されません。

これらの試みはすべて夜遅くに行われたため、非常に明白なことを見落としている可能性は十分にありますが、どんな助けでも大歓迎です。

何をやろうとしているかによると思いますが、公式のDiscord Ruby APIを使用してデータをDiscourse DBに取り込み、クライアントにシリアライズしてからウィジェットで使用してはいかがでしょうか?

ほとんどの用途にはアプリケーションのAPIで十分なため、不必要な複雑さのように思えましたが、正直なところ、DiscourseのRuby側についてもう少し勉強する必要があるため、実装を誤解している可能性もあります。

ただし、投稿デコレーションが機能しない場合は、その方法を選択することになるでしょう。

@merefield に感謝の意を伝えるために、シリアライズについてさらに調査したところ、JavaScript から呼び出す代わりにシリアライザー内で API を呼び出すことでタスクを達成できました。

これが推奨されない理由は数多くあると思いますが、私にとってはうまくいったので、この方法で進めます。将来この情報を見つけた方のために、シリアライザーにデータを追加するには次のコードを使用できます。

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

これにより、reopenWidget の呼び出し内でデータにアクセスできるようになります。私の場合は、トピックに関連するデータを topic_view シリアライザーに追加し、次のように投稿を変更しながらアクセスしています。

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

            // データの処理

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

前述したように、これはおそらく推奨されない方法である理由はたくさんありますが、ロード時間への影響は最小限で、私のユースケースでは機能しています。

何らかの理由で JavaScript 内でタスクを達成したいと考えている方のために、関連するコードは、投稿を復号化する discourse-encrypt プラグインに存在するように思われますが、この方法の方が実装がはるかに簡単でした: discourse-encrypt/assets/javascripts/discourse/initializers/decrypt-posts.js at 255724ebc5fc3956f26beca09c1f7cb273d76eb2 · discourse/discourse-encrypt · GitHub

奇妙なことに、これは画像のサイズが大きくなりすぎるため、Topic Thumbnails テーマコンポーネントを壊してしまうようです GitHub - discourse/discourse-topic-thumbnails: Display thumbnails in topic lists

本当に奇妙な相互作用ですが、他に気づいたことはありません。

うーん…それは建築的に健全ではないと思います。バックエンドソリューション(特に認証と認可が関わる場合、リモートサーバー呼び出しはほとんど常にバックエンドのプロセス間で行われるべきです)を検討しているのは素晴らしいことですが、データは非同期でロードされるべきであり、シリアライザーは完了のためにリモート呼び出しに依存すべきではありません。少なくとも、その呼び出しをキャッシュでラップすべきではないでしょうか?

試してみて、ページのロードタイミングがその変更の前と後でどのように変わるかに細心の注意を払ってください。大幅な遅延を導入する可能性があります。

実際には、ロードごとに10〜50ミリ秒程度追加されるだけです。両方のボックスが同じデータセンターに存在するため、接続は超低遅延です。実際、コンポーネントにデータをプルするために使用している方法は、Discourseが独自の静的ページをレンダリングするよりもわずかに速くページをロードします(約100ミリ秒の違い)。これには、Discord IDを使用してAPIレスポンスにユーザーデータを追加してからクライアントに転送するDB操作も含まれます。(Rubyは外部アプリケーションからデータをリクエストし → JSONを解析し → DBクエリを実行し、レスポンスにデータを追加するためにeachループを実行し → JSONを生成してフロントエンドクライアントに返します)。コードベースの大きさを考えると理解できますが、伝統的に「高コスト」と見なされるこれらのリクエストが完全に unnoticed になる余地を生む内部的なオーバーヘッドが確かに存在します。とはいえ、これは光速と音速の話であり、エンドユーザーにとってはDiscourseが素晴らしいプラットフォームであるため、依然として信じられないほど高速です。

キャッシュは素晴らしい追加機能であり、調査する予定です。Rubyは非常に初心者なので、利用可能な関数についてさらに学ぶにつれて更新します。現時点ではハッキーな方法かもしれませんが、これに対する何らかの方法は、プラグイン開発の側面にとって非常に有益である可能性があるため、今後更新していくつもりです。既存のアプリケーションを持つ人々にとって、彼らが知っているAPIを使用して、必要なデータを必要な場所に効率的にスライドさせることができることは、データベースとDiscourse間でデータを同期するためのシステムを構築したり、追加のモデルやDBマイグレーションをいじったりする必要がなくなり、開発時間を大幅に短縮し、プラグイン作成者をアプリケーションの(つまり、プラグインAPIの)より適切に文書化された領域に留めることができます。

洞察に大変感謝しており、このプラットフォームについてさらに学び、将来的には貢献できることを楽しみにしています。

「いいね!」 3

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