ディレクトリアイテムシリアライザへのユーザー属性の追加

クライアントから、カード形式のユーザーディレクトリを作成するよう依頼を受けました。

クライアントは discourse.org でホストされているため、当初(パフォーマンス上の問題とは別に)これは不可能だとお伝えしました。ユーザーカードを埋めるために必要な属性は、ディレクトリ項目と共にシリアライズされるユーザーオブジェクトには存在しないためです。

しかし、さらに議論を重ねた結果、コアにプルリクエスト(PR)を送り、サイト設定を通じてユーザー属性をディレクトリ項目のシリアライザーに追加するというアプローチが可能であると判断しました。この機能は、さまざまなユーザー属性の組み合わせを必要とする、さまざまなスタイルのユーザーディレクトリに有用になるという考えからです(例は後述)。

これについて実験した結果、比較的シンプルなアプローチを見出しました。その詳細は以下の差分で確認できます:

https://github.com/discourse/discourse/compare/master...angusmcleod:directory_user_attribute_whitelist

具体的には:

  1. 専用の DirectoryItemUserSerializer を作成します(現在の DirectoryItemSerializer 内部にある UserSerializer は、私にはいつも少し奇妙に感じられていました)。

  2. サイト管理者が追加するユーザー属性を選択した場合:

    1. シリアライザーの保護機能(スタッフ/プライベート/信頼されていない属性など)を活用するために、シリアライズされたユーザーを作成します。

    2. UserSerializer のフィルターを通過した追加属性をシリアライズします。

ここでの目標は以下の通りです:

  1. 既存の動作を一切変更しないこと。

  2. 要求された属性のみをシリアライズすること。

もし皆さんがこのアプローチや要望に賛同いただけるようであれば、以下の作業を完了させます:

  1. サイト設定に対するバリデーションの追加(入力された文字列がユーザー属性であることを確認するため)。

  2. テストの追加。

ただし、まずは皆さんにご確認いただくのが良いと考えました。

この機能により可能になる機能の例として、以下のスクリーンショットは、ローカル環境でこのコアの変更と、既存のディレクトリをオーバーライドし、修正されたユーザーカードコンポーネントを使用するテーマコンポーネントを組み合わせて表示したものです:

@sam このアプローチは PR で実現可能だと思いますか?

@blake@awesomerobot が、同様の要件を持つ別の顧客と作業を進めていると認識しています。always_include_topic_excerpts のようなサイト設定にも、私は概ね賛成です。

ただし、条件として、これがテスト済みであること、そしてサイト設定は非表示であることが必要です。

david さんもこの問題に関心を持っていることは承知しています。私は少し迷っていますが、よりクリーンな長期的な解決策としては、以下のようなものが考えられます:

  1. プラグインやテーマが追加のシリアル化情報をオプトインできるようにする「隠しサイト設定」を追加する(デフォルトはオフ)
  2. テーマやプラグイン向けに、追加情報を「要求」するためのプロトコルを用意する。

この利点は、一部のテーマのみが追加のシリアル化情報を持つことができる点です。

David さんの意見をもう少し伺ってから、あなたにゴーサインを出すことにします。

ユーザーディレクトリシリアライザーに users.json?include_profile=true のような新しいパラメータを受け付けるようにするのはどうでしょうか。

そうすれば、テーマがこのパラメータを追加できるようにする JS プラグイン API を追加できます。

api.userListIncludeProfile(true)

「プロフィール」には、通常のユーザーシリアライザーに含まれるすべてのものが含まれます(n+1 クエリが発生しないように注意してください)。個別のフィールドを指定してもパフォーマンスへの影響はほとんどない我认为ので、シンプルに保つべきだと考えます。

同じアプローチはトピックリスト ?include_excerpts=true にも適用できます。

また、この方法なら「テーマごとのシリアライザー設定」が匿名キャッシュによって壊れることもありません。

@sam さん、どう思いますか?

近いですが、これは完全に動作しません。サイトのホームページや u パスにアクセスする際に、パスにパラメータを追加する余地がないためです。デフォルト値の変更が必要です :frowning:

ああ、そうですか :cry:

その場合、隠しサイト設定が良い出発点だと思います。テーマごとに設定できると良いのですが、まずそのための基盤を整える必要があります。それでも、ブーリアンの「ユーザーリストにプロフィールを含む」設定の方が、扱いやすいと考えています。

ユーザーカードで使われている featured_user_badges のようなプロパティも含まれますか?

はい、そう思います。通常のユーザーシリアライザーに含まれているものはすべて(N+1 問題を発生させない範囲で)含められます。

いいですね。もし pr-welcome として受け入れるご意向があれば、その形態についてお知らせください。喜んで作成いたします。こちらからは @fzngagan が引き続き対応いたします。

関連する情報をすべて追加する、単一のブール型非表示サイト設定で進めましょう。

david さん、ご指摘ありがとうございます。月曜日から調査を始めます。

ここで明確にしたいのは、追加データをリクエストするためのprotocolです。フロントエンドのサイト設定に頼ってデータをリクエストできるでしょうか、それともご提案いただいたように、plugin-api に別の API を追加するべきでしょうか?

シンプルにいきましょう。パラメータと JavaScript API に関する私の投稿は無視してください。

サーバーでサイト設定が有効になっている場合は、追加情報を返してください。無効になっている場合は返さないでください。

現時点では、管理者が手動でこの設定を有効にする必要があります。将来的には、テーマがこの設定を自動的に切り替えられるようにする検討も行うかもしれません。

はい、テーマコンポーネントは、設定が有効な場合にのみ追加フィールドを条件付きで消費するべきですね?

また、サーバーも、設定が有効な場合のみ追加フィールドを送信する必要があります。

@david ありがとうございます、David。PR を作成して、改めてご連絡いたします。

@david PRを作成しました

cc @angus

ここで閉ループします。ディレクトリシリアライザーにさらに属性を追加しないことを決定しました。代わりに、ユーザーシリアライズの性能を大幅に向上させました。ユーザーカードを独自のルートに分割し[Changes to the user card data source]、複数のカードを一度に返す新しいルートを追加しました[FEATURE: New route for loading multiple user cards simultaneously (#9… · discourse/discourse@ff62911 · GitHub]。

この新しいルートの使用例は、以下のテーマコンポーネントで見つけることができます: