URLクエリパラメータを使用してカスタムトピックリストフィルタ(例:価格、場所)を構築している間、URLは正しく更新されます(例:...?market_item_statuses=Available)、しかしサーバーのtopic_query.optionsにはパラメータが表示されません。
設定:
-
クライアント側のパラメータ登録 (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 });
});
});
-
サーバー側のホワイトリスト設定試み (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
-
サーバー側のフィルタリングロジック (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
ログの問題:
-
パラメータのホワイトリスト登録失敗:
[Tecenc] 警告: TopicQuery用のadd_custom_param_handlerまたはextra_options_whitelistの適切な方法が見つかりません。
-
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(およびその他のカスタムパラメータ)は存在していません。
私たちの環境:
質問:
- 最近のDiscourseバージョンでカスタムURLクエリパラメータを
topic_query.optionsに確実に渡すための現在のベストプラクティスは何ですか?
- なぜ私たちの
add_custom_param_handlerやextra_options_whitelistの使用試みが「適切なメソッドが見つからない」という警告で失敗しているのでしょうか?
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]
これまでの進行状況の報告:
-
静的な TopicQuery ホワイトリストメソッド(add_custom_param_handler や extra_options_whitelist など)が私の Discourse バージョンではクラスメソッドとして利用できないことを確認し、そのアプローチは断念しました。
-
ListController#build_topic_list_options にパッチを実装し、TopicQuery.new が呼び出される前に私のカスタムURLパラメータ(例:market_item_statuses、market_price_min)を opts ハッシュにインジェクトしました。
-
この部分は現在正常に動作しています! /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]...の行はありません)からのログは、この失敗したリクエストについて表示されません。
これは、TopicQueryがoptsハッシュ(現在は私のカスタムパラメータを含む)を使って初期化された後に、discourseのコアのTopicQuery#apply_custom_filtersメカニズムが私の登録した(そして非常にシンプルな)フィルターブロックを実行しようとするときに、500エラーが発生することを示しています。
development.logからの特定のRuby例外と完全なスタックトレースを抽出するのに困難を感じており、これらが「Completed 500…」行の直前にあるはずです(収集したログの断片は500行自体は示していますが、その詳細なエラーメッセージは含まれていません)。
追記の質問:
これらの状況において、
-
ListControllerのパッチによってTopicQuery.optionsに成功裏にカスタムパラメータが注入されている。
-
これらのカスタムパラメータがoptsに存在するときに500エラーが発生している。
-
そして、この500エラーは、カスタムパラメータを持つリクエストの最初の行にある、最も簡略化されたカスタムフィルターブロック(ただ ログ記録と元のrelationを返すだけのもの)が実行される前に起こる。
-
これはDiscourse 3.5.0.beta3-dev上で発生している。
TopicQuery自体、またはapply_custom_filtersメソッドが、登録済みのカスタムフィルターブロックを呼び出す前にエラーを出す原因は何でしょうか?特に、optionsハッシュにこれらのプラグイン固有のキーが含まれている場合です。以前疑っていたLocalJumpErrorが、シンプルなブロックでも影響している可能性はありますか?
これらの条件下でTopicQueryの挙動で確認すべき次のポイントや、もしこの状況のフルバックトレースを堅牢に取得する方法について、何かアドバイスがあれば非常に助かります。" } }