DEV: Allow specifying a condition when preloading topics for topic list (#32101)

Currently when using `register_topic_preloader_associations`, we are
not able to specify a condition that is evaluated at runtime.

This commit allows specifying a condition and also keeps backward
compatibility.

```
   register_topic_preloader_associations(:linked_topic) { true }
   register_topic_preloader_associations({
     first_post: [uploads]
   })
```
This commit is contained in:
Natalie Tay
2025-04-01 16:50:16 +08:00
committed by GitHub
parent b37591632d
commit 2a26555a7a
3 changed files with 37 additions and 10 deletions

View File

@ -138,7 +138,15 @@ class TopicList
{ category: :parent_category },
]
topic_preloader_associations.concat(DiscoursePluginRegistry.topic_preloader_associations.to_a)
DiscoursePluginRegistry.topic_preloader_associations.each do |a|
fields = a[:fields]
condition = a[:condition]
if condition.present?
topic_preloader_associations << fields if condition.present? && condition.call
else
topic_preloader_associations << fields
end
end
ActiveRecord::Associations::Preloader.new(
records: @topics,

View File

@ -1347,6 +1347,24 @@ class Plugin::Instance
end
end
# This method allows plugins to preload topic associations when loading topics
# that make use of topic_list.
#
# @param fields [Symbol, Array<Symbol>, Hash] The topic associations to preload.
#
# @example
# register_topic_preloader_associations(:first_post)
# register_topic_preloader_associations([:first_post, :topic_embeds])
# register_topic_preloader_associations({ first_post: :uploads })
# register_topic_preloader_associations({ first_post: :uploads }) do
# SiteSetting.some_setting_enabled?
# end
#
# @return [void]
def register_topic_preloader_associations(fields, &condition)
DiscoursePluginRegistry.register_topic_preloader_association({ fields:, condition: }, self)
end
protected
def self.js_path
@ -1441,10 +1459,6 @@ class Plugin::Instance
reloadable_patch { NewPostManager.add_plugin_payload_attribute(attribute_name) }
end
def register_topic_preloader_associations(fields)
DiscoursePluginRegistry.register_topic_preloader_association(fields, self)
end
##
# Allows plugins to preload topic associations when loading categories with topics.
#

View File

@ -1305,17 +1305,22 @@ RSpec.describe TopicQuery do
context "when preloading associations" do
it "preloads associations" do
DiscoursePluginRegistry.register_topic_preloader_association(
:first_post,
Plugin::Instance.new,
)
plugin = Plugin::Instance.new
plugin.register_topic_preloader_associations(:topic_embed)
plugin.register_topic_preloader_associations({ first_post: [:uploads] })
plugin.register_topic_preloader_associations(:user_warning) { true }
plugin.register_topic_preloader_associations(:linked_topic) { false }
topic = Fabricate(:topic)
Fabricate(:post, topic: topic)
new_topic = topic_query.list_new.topics.first
expect(new_topic.association(:image_upload).loaded?).to eq(true) # Preloaded by default
expect(new_topic.association(:first_post).loaded?).to eq(true) # Testing a user-defined preloaded association
expect(new_topic.association(:topic_embed).loaded?).to eq(true) # Testing a user-defined preloaded association
expect(new_topic.association(:first_post).loaded?).to eq(true) # Nested preloaded association
expect(new_topic.first_post.association(:uploads).loaded?).to eq(true) # Nested preloaded association
expect(new_topic.association(:user_warning).loaded?).to eq(true) # Conditionally loaded
expect(new_topic.association(:linked_topic).loaded?).to eq(false) # Failed condition
expect(new_topic.association(:user).loaded?).to eq(false) # Testing the negative
DiscoursePluginRegistry.reset_register!(:topic_preloader_associations)