FEATURE: Add on_preload for TopicView (#13122)

FEATURE: Add on_preload for TopicView (#13122)

This allows plugins to load data on fetched posts before each post is individually serialized.

diff --git a/lib/topic_view.rb b/lib/topic_view.rb
index dcdec08..160c504 100644
--- a/lib/topic_view.rb
+++ b/lib/topic_view.rb
@@ -4,6 +4,25 @@ class TopicView
   MEGA_TOPIC_POSTS_COUNT = 10000
   MIN_POST_READ_TIME = 4.0
 
+  def self.on_preload(&blk)
+    (@preload ||= Set.new) << blk
+  end
+
+  def self.cancel_preload(&blk)
+    if @preload
+      @preload.delete blk
+      if @preload.length == 0
+        @preload = nil
+      end
+    end
+  end
+
+  def self.preload(topic_view)
+    if @preload
+      @preload.each { |preload| preload.call(topic_view) }
+    end
+  end
+
   attr_reader(
     :topic,
     :posts,
@@ -106,6 +125,8 @@ class TopicView
       end
     end
 
+    TopicView.preload(self)
+
     @draft_key = @topic.draft_key
     @draft_sequence = DraftSequence.current(@user, @draft_key)
 
diff --git a/spec/components/topic_view_spec.rb b/spec/components/topic_view_spec.rb
index c4a104c..d934128 100644
--- a/spec/components/topic_view_spec.rb
+++ b/spec/components/topic_view_spec.rb
@@ -15,6 +15,23 @@ describe TopicView do
 
   let(:topic_view) { TopicView.new(topic.id, evil_trout) }
 
+  context "preload" do
+    it "allows preloading of data" do
+      preloaded_topic_view = nil
+      preloader = lambda do |view|
+        preloaded_topic_view = view
+      end
+
+      TopicView.on_preload(&preloader)
+
+      expect(preloaded_topic_view).to eq(nil)
+      topic_view
+      expect(preloaded_topic_view).to eq(topic_view)
+
+      TopicView.cancel_preload(&preloader)
+    end
+  end
+
   it "raises a not found error if the topic doesn't exist" do
     expect { TopicView.new(1231232, evil_trout) }.to raise_error(Discourse::NotFound)
   end

GitHub sha: ca809d2c

This commit appears in #13122 which was approved by davidtaylorhq. It was merged by danielwaterworth.