基本的なトピックカスタムフィールドを追加する方法

トピックにカスタムフィールドを追加する方法を理解しようとしており、非常に基本的な例に取り組んでいます。目標は、各作成されたトピックに「sample_field」という名前のカスタムフィールドを追加し、単純な文字列値を持たせることです。

いくつかの例を確認しました。例えばpoll pluginsolved plugin、そしてこのディスカッションなどです。しかし、これらのプラグインはカスタムフィールドに対して非常に多くのことを行っているため、必要な基本的なコードがまだよくわかりません。

そのため、まだ完璧ではありません。plugin.rbファイルに何かが不足している(と思います)し、トピックが作成される時点で文字列値をカスタムフィールドにバインドする方法もまだ見つけていません。

これを動作させるには何が必要でしょうか?

ご支援いただければ幸いです。ありがとうございます!

以下が現在のコードです。

plugin.rb:
//カスタムフィールドの作成:

  after_initialize do
     Topic.register_custom_field_type('sample_field', :string)
     add_to_serializer(:topic_view, :custom_fields) { object.custom_fields } //クライアント側でカスタムフィールドを表示したい場合
  end

assets/javascripts/initializers/topic-custom-field.js.es6:
//カスタムフィールドオブジェクトを初期化し、サーバーに送信できるようにする:

import { withPluginApi } from 'discourse/lib/plugin-api';

export default {
  name: 'topic-custom-field',
  initialize() {
    withPluginApi('0.8.31', api => {
      api.modifyClass('model:topic', {
        custom_fields: {},
        asJSON() {
          return Object.assign(this._super(), {
            custom_fields: this.custom_fields
          });
        }
      })
    })
  }
}

では、トピックが保存される時点でカスタムフィールドの値をどのように追加すればよいでしょうか?

トピックの「save」アクションは、コードベースの以下の箇所で発生すると考えています。

app/templates/composer.hbs:

  <div class="save-or-cancel">
            {{#unless model.viewFullscreen}}
              {{composer-save-button action=(action "save")
                                     icon=saveIcon
                                     label=saveLabel
                                     disableSubmit=disableSubmit}}
...

その「save」アクションが発生したときに、何か(この場合はカスタムフィールドに値を追加する)を行うにはどうすればよいでしょうか?

initializers以下にjsファイルを作成し、以下のような処理を試みました。

api.modifyClass('component:composer-save-button', {
   actions: {
       topic.set('custom_fields.sample_field', 'here's a value for the sample_field')
   }
}

しかし、その「topic.set」をcomposer.hbsの「save」アクションにリンクさせる必要があり、その方法がわかりません。


もしより簡単な方法があれば、ぜひ教えてください!

「いいね!」 2

完璧な例をすぐに思い浮かべることはできませんが、将来的に作成するかもしれません。

他のプラグインをいくつか見て、例を探してみるのも良いでしょう。すぐにどのプラグインが該当するかはわかりませんが、「all-the-plugins」という名前の Discourse リポジトリがあり、私はよくそこでグリープして情報を探しています。

現在テスト中の「reactions」プラグインがよい例ではないでしょうか。バナーを表示して、それを見てみてください。

「いいね!」 2

はい、既存のプラグインを常に確認してください。

例を以下に示します:

これは、以下のコネクタとコンポーネントに依存しています:

「いいね!」 2

みなさん、ありがとうございます。これらを確認します。元の投稿でも触れましたが、すでに多くの他の例もレビュー済みです。私が提供したコードについて、ご意見はありますか?

「いいね!」 2

申し訳ありません。私には明らかな問題は見つかりませんでした。プラグイン開発のスキルは向上しつつありますが、それでも「少し知っているが、それが逆に危険になる」という感覚をしばしば抱いています。

「いいね!」 2

「Discourse流のやり方」にこだわれば、おそらく過剰な複雑さになるかもしれません。つまり、トピックメタエリア内でデータを編集し、後でペンのアイコンをクリックした時点でのみ反映させる方法です。

正しく接続された入力ボックスをレンダリングし、その値をトピックビューにシリアライズすることだけが必要です。

PostRevisorのコードがカスタムフィールドの更新を自動的に処理してくれます。

Locationsプラグインの例をご覧ください。それさえも、あなたが必要とするものよりも多いかもしれません。

Locationsプラグインを実行して、その動作を確認してください。

「いいね!」 2

こちらは、わずかに異なる入力シナリオですが、同じメカニズムとフックを活用した別の例です:

https://github.com/paviliondev/discourse-topic-previews/blob/master/assets/javascripts/discourse/connectors/edit-topic/select-thumbnail-connector.hbs

「いいね!」 4

ありがとうございます。PostRevisor は詳しくありませんが、現在確認しています。

「トピックメタエリア」というのが何を指すのか、よくわかりません。特定のファイルを想定されていますか?(UI の観点では、作成用のコンポーザー(その中に d エディターがあります)と、トピック表示そのものがあることはわかっています。「メタ」エリアがどこにあるのかは確信が持てません。)

「いいね!」 2

カテゴリとタグの情報はメタデータであると私は考えます。

「いいね!」 2

トピックのカスタムフィールドを作成し、それを設定する現在動作する基本的な例を示します。これは、トピック表示ページで特定のボタンがクリックされた際にフィールドを設定するものです。

プラグインでトピックカスタムフィールドを使用しているものを見ると、plugin.rb 内で PostRevisor(例:PostRevisor.track_topic_field)や DiscourseEvent.on(:topic_created) do |topic|... が一般的に使用されていることに気づきます。これらを使えば、ボタンをクリックする必要なくカスタムフィールドを設定できるかもしれません。例えば、トピック作成時にカスタムフィールドを設定するような場合です。しかし、私はまだその方法を突き止めていません。

[編集:トピック作成時にカスタムフィールドの値を追加するための plugin.rb のコードを提案してくださる方がいらっしゃいましたら、ぜひお願いします!(ボタンをクリックする別の手順を設けるのではなく)]

そこで、そのような高度な機能を使わずに動作する基本的な例を以下に示します。

plugin.rb

Topic.register_custom_field_type('sample_field', :string)
add_to_class(:topic, :sample_field) { self.custom_fields['sample_field'] } ## 多分不要。discourse-locations プラグインの plugin.rb の 83 行目に基づく
\t
add_to_serializer(:topic_view, :sample_field, false) { object.topic.sample_field } ## ユーザーにカスタムフィールドの結果を表示したい場合のみおそらく必要

connector/[add-button].hbs

// ここでの例:connector は topic-above-post-stream であり、プラグイン outlet にモデル(topic)を渡しています

<button {{action "setThatTopic" model}}>Click Here</button>

connector/[add-button].js.es6

import Topic from 'discourse/models/topic';  // 多分不要

export default {            
    actions: {
       setThatTopic(model){
           model.set('custom_fields.sample_field', 'newValue123')
           console.log('testing that custom field is there = ' + JSON.stringify(model.custom_fields))
        }
     }
}

assets/javascripts/initializers/topic-custom-field.js.es6

// これは多分不要です。ただし、カスタムフィールドオブジェクトを初期化し、サーバーに送信できるようにするというのがアイデアです:

import { withPluginApi } from 'discourse/lib/plugin-api';

export default {
    name: 'topic-custom-field',
     initialize() {
\t   withPluginApi('0.8.31', api => {
\t\t api.modifyClass('model:topic', {
\t\t\tcustom_fields: {},
\t\t\tasJSON() {
\t\t\t    return Object.assign(this._super(), {
\t\t\t\tcustom_fields: this.custom_fields
\t\t\t   });
\t\t\t}
\t     })
\t   })
    }
}
「いいね!」 6

「教育プラグイン」を公開しました。この方法を示すものです

「いいね!」 9

@angus さん、ありがとうございます。これは非常に役立ち、Discourse でのコーディングをより容易にするまさに必要な内容です。個人的には、Discourse の様々なタスク(カテゴリやグループのカスタムフィールドなど)に対して、このように「要点を絞った、最小限の、1 つの機能の実装に特化したコード例」というリソースを多く見てみたいですね。このようなリソースは、時間の節約に大変役立ちます。

「いいね!」 3