カスタムトピックフィルタ:URLパラメータが`TopicQuery.options`に到達しない

URLクエリパラメータを使用してカスタムトピックリストフィルタ(例:価格、場所)を構築している間、URLは正しく更新されます(例:...?market_item_statuses=Available)、しかしサーバーのtopic_query.optionsにはパラメータが表示されません。

設定:

  1. クライアント側のパラメータ登録 (tecenc-discovery-params.js):

    // tecenc-discovery-params.js
    import { apiInitializer } from "discourse/lib/api";
    
    export default apiInitializer("1.37.3", (api) => {
      const MARKET_PARAMS_KEYS = [
        "market_price_min", "market_price_max", "market_location",
        "market_conditions", "market_warranty", "market_item_statuses"
      ];
      MARKET_PARAMS_KEYS.forEach(paramKey => {
        api.addDiscoveryQueryParam(paramKey, { replace: true, refreshModel: true });
      });
    });
    
  2. サーバー側のホワイトリスト設定試み (plugin.rb):

    # plugin.rb
    module ::Tecenc
      MARKET_PARAMS_KEYS = [
        :market_price_min, :market_price_max, :market_location,
        :market_conditions, :market_warranty, :market_item_statuses
      ].freeze
    end
    
    # after_initialize do
      if SiteSetting.tecenc_enabled?
        if defined?(::TopicQuery.add_custom_param_handler)
          ::Tecenc::MARKET_PARAMS_KEYS.each do |param_key|
            ::TopicQuery.add_custom_param_handler(param_key) { |value| value } # 簡略化のため
          end
          Rails.logger.info "[Tecenc] add_custom_param_handlerで登録しました。"
        elsif defined?(::TopicQuery) && ::TopicQuery.methods.include?(:extra_options_whitelist)
          current_whitelist = ::TopicQuery.extra_options_whitelist || []
          new_whitelist = (current_whitelist + ::Tecenc::MARKET_PARAMS_KEYS).uniq
          ::TopicQuery.extra_options_whitelist(*new_whitelist)
          Rails.logger.info "[Tecenc] extra_options_whitelistを拡張しました。"
        else
          Rails.logger.warn "[Tecenc] 警告: TopicQueryのパラメータホワイトリスト方法が見つかりません。"
        end
    
  3. サーバー側のフィルタリングロジック (plugin.rb):

    # plugin.rb (after_initialize内 / 有効時)
    ::TopicQuery.add_custom_filter(:"tecenc_filters") do |topics, topic_query|
      opts = topic_query.options
      Rails.logger.info "[Tecenc_TopicQuery] オプション: #{opts.inspect}" # 重要なログ
    
      # market_params_present = ::Tecenc::MARKET_PARAMS_KEYS.any? { |p| opts[p].present? }
      # if market_params_present
      #   # ... opts[key]を使用したフィルタリングロジック ...
      # end
      topics # または修正された_topics
    end
    

ログの問題:

  1. パラメータのホワイトリスト登録失敗:

    [Tecenc] 警告: TopicQuery用のadd_custom_param_handlerまたはextra_options_whitelistの適切な方法が見つかりません。
    
  2. TopicQuery.add_custom_filter内のoptsにカスタムパラメータが含まれていません:
    URLが...?market_item_statuses=Availableのときのログは次のように表示されます:

    [Tecenc_TopicQuery] オプション: {:category=>5, :filter=>"default", :topic_ids=>nil, :category_id=>5}
    

    私たちの market_item_statuses(およびその他のカスタムパラメータ)は存在していません。

私たちの環境:

質問:

  1. 最近のDiscourseバージョンでカスタムURLクエリパラメータをtopic_query.optionsに確実に渡すための現在のベストプラクティスは何ですか?
  2. なぜ私たちのadd_custom_param_handlerextra_options_whitelistの使用試みが「適切なメソッドが見つからない」という警告で失敗しているのでしょうか?
  3. TopicQueryとのパラメータ登録に代わる方法はありますか?

ご協力いただけると幸いです!

add_custom_param_handlerはTopicQueryのメソッドとして利用できないことに気づきました。より新しいDiscourseバージョンでトピックのカスタムフィルターを構築する別の方法はありますか?

TopicQueryのシングルトンメソッド: [:add_custom_filter, :apply_custom_filters, :new_filter, :public_valid_options, :remove_custom_filter, :remove_muted_tags, :results_filter_callbacks, :results_filter_callbacks=, :tracked_filter, :unread_filter, :valid_options, :validate?, :validators, :yaml_tag]

これまでの進行状況の報告:

  1. 静的な TopicQuery ホワイトリストメソッド(add_custom_param_handlerextra_options_whitelist など)が私の Discourse バージョンではクラスメソッドとして利用できないことを確認し、そのアプローチは断念しました。

  2. ListController#build_topic_list_options にパッチを実装し、TopicQuery.new が呼び出される前に私のカスタムURLパラメータ(例:market_item_statusesmarket_price_min)を opts ハッシュにインジェクトしました。

  3. この部分は現在正常に動作しています! /c/market/5/l/latest.json?filter=defaultmarket_item_statuses=Available のようなリクエストを行うと、サーバーログがインジェクションを確認します:

    [TecencMarket_ListControllerExt_BuildOptsV3] optsにインジェクトされました: market_item_statuses = Available
    
    

    つまり、TopicQuery.new(user, opts) は、私のカスタムパラメータを含む opts を受け取っています。

現在の問題点: 500エラーとフィルターブロック未通過

パラメータが正しくTopicQueryのイニシャライザに渡されているにもかかわらず、これらのカスタムマーケットパラメータを含むリクエスト時に 500 Internal Server Error が発生し続けます。

これを切り分けるために、TopicQuery.add_custom_filter(:"tecenc_market_filters")ブロックを最も簡潔な形に簡略化しました。

# plugin.rb - 現在の簡略化されたカスタムフィルターブロック
if ::TopicQuery.respond_to?(:add_custom_filter)
  ::TopicQuery.add_custom_filter(:"tecenc_market_filters") do |topics, topic_query|
    original_topics_relation = topics 
    opts = topic_query.options
    log_prefix_query = "[TecencMarket_SimplifiedFilter_V1.1_Test]" # デバッグ用プレフィックス

    Rails.logger.info "#{log_prefix_query} TopicQueryから受け取ったOpts: #{opts.inspect}"

    if opts[:market_item_statuses].present?
      Rails.logger.info "#{log_prefix_query} 'market_item_statuses'はoptsに存在します: #{opts[:market_item_statuses]}"
    else
      Rails.logger.info "#{log_prefix_query} 'market_item_statuses'はoptsに存在しません。"
    end
    
    Rails.logger.info "#{log_prefix_query} 元のトピック関係を返します。"
    original_topics_relation # 暗黙的な返り値
  end
  Rails.logger.info "[TecencMarket] 簡略化されたカスタムフィルター(V1.1_Test)を適用しました。"
end

この簡略化されたフィルタの観察結果:

  • カスタムフィルタパラメータを含まないリクエスト(例:/c/market/5/l/latest.json?filter=default のみ):

    • 簡略化されたフィルターブロックのログは正常に出力されます:

      [TecencMarket_SimplifiedFilter_V1.1_Test] TopicQueryに渡されたOpts: {:category=>5, :filter=>"default", ...}
      [TecencMarket_SimplifiedFilter_V1.1_Test] 'market_item_statuses'はoptsに存在しません。
      [TecencMarket_SimplifiedFilter_V1.1_Test] 元のトピック関係を返します。
      
      
    • ページは 200 OK で表示されます。

  • カスタムフィルタパラメータを含むリクエスト(例:/c/market/5/l/latest.json?filter=defaultmarket_item_statuses=Available):

    • ListControllerのパッチログに以下のようなログが出力されます:[TecencMarket_ListControllerExt_BuildOptsV3] Injected into opts: market_item_statuses = Available

    {“type”:“object”,“properties”:{“translation”:"* Completed 500 Internal Server Error in ...msは直後に発生します。

    • 重要なポイントとして、簡略化されたフィルターブロック内から([TecencMarket_SimplifiedFilter_V1.1_Test]...の行はありません)からのログは、この失敗したリクエストについて表示されません。

これは、TopicQueryoptsハッシュ(現在は私のカスタムパラメータを含む)を使って初期化された後に、discourseのコアのTopicQuery#apply_custom_filtersメカニズムが私の登録した(そして非常にシンプルな)フィルターブロックを実行しようとするときに、500エラーが発生することを示しています。

development.logからの特定のRuby例外と完全なスタックトレースを抽出するのに困難を感じており、これらが「Completed 500…」行の直前にあるはずです(収集したログの断片は500行自体は示していますが、その詳細なエラーメッセージは含まれていません)。

追記の質問:

これらの状況において、

  1. ListControllerのパッチによってTopicQuery.optionsに成功裏にカスタムパラメータが注入されている。

  2. これらのカスタムパラメータがoptsに存在するときに500エラーが発生している。

  3. そして、この500エラーは、カスタムパラメータを持つリクエストの最初の行にある、最も簡略化されたカスタムフィルターブロック(ただ ログ記録と元のrelationを返すだけのもの)が実行される前に起こる。

  4. これはDiscourse 3.5.0.beta3-dev上で発生している。

TopicQuery自体、またはapply_custom_filtersメソッドが、登録済みのカスタムフィルターブロックを呼び出す前にエラーを出す原因は何でしょうか?特に、optionsハッシュにこれらのプラグイン固有のキーが含まれている場合です。以前疑っていたLocalJumpErrorが、シンプルなブロックでも影響している可能性はありますか?

これらの条件下でTopicQueryの挙動で確認すべき次のポイントや、もしこの状況のフルバックトレースを堅牢に取得する方法について、何かアドバイスがあれば非常に助かります。" } }