DEV: Refactor draft attributes for `CategoryList` and `TopicList`.

DEV: Refactor draft attributes for CategoryList and TopicList.

Avoid repeating the same logic in a bunch of places which will allow us to make changes to the draft attributes easier in the future.

diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb
index 24eb841..a0cbe54 100644
--- a/app/controllers/categories_controller.rb
+++ b/app/controllers/categories_controller.rb
@@ -30,12 +30,6 @@ class CategoriesController < ApplicationController
     }
 
     @category_list = CategoryList.new(guardian, category_options)
-    @category_list.draft_key = Draft::NEW_TOPIC
-    @category_list.draft_sequence = DraftSequence.current(
-      current_user,
-      Draft::NEW_TOPIC
-    )
-    @category_list.draft = Draft.get(current_user, Draft::NEW_TOPIC, @category_list.draft_sequence) if current_user
 
     if category_options[:is_homepage] && SiteSetting.short_site_description.present?
       @title = "#{SiteSetting.title} - #{SiteSetting.short_site_description}"
@@ -264,15 +258,9 @@ class CategoriesController < ApplicationController
       result.topic_list = TopicQuery.new(nil, topic_options).list_top_for(SiteSetting.top_page_default_timeframe.to_sym)
     end
 
-    draft_key = Draft::NEW_TOPIC
-    draft_sequence = DraftSequence.current(current_user, draft_key)
-    draft = Draft.get(current_user, draft_key, draft_sequence) if current_user
-
-    %w{category topic}.each do |type|
-      result.public_send(:"#{type}_list").draft = draft
-      result.public_send(:"#{type}_list").draft_key = draft_key
-      result.public_send(:"#{type}_list").draft_sequence = draft_sequence
-    end
+    result.topic_list.draft = result.category_list.draft
+    result.topic_list.draft_key = result.category_list.draft_key
+    result.topic_list.draft_sequence = result.category_list.draft_sequence
 
     render_serialized(result, CategoryAndTopicListsSerializer, root: false)
   end
diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb
index 471d3b2..2dfa106 100644
--- a/app/controllers/tags_controller.rb
+++ b/app/controllers/tags_controller.rb
@@ -86,10 +86,6 @@ class TagsController < ::ApplicationController
         @list = TopicQuery.new(current_user, list_opts).public_send("list_#{filter}")
       end
 
-      @list.draft_key = Draft::NEW_TOPIC
-      @list.draft_sequence = DraftSequence.current(current_user, Draft::NEW_TOPIC)
-      @list.draft = Draft.get(current_user, @list.draft_key, @list.draft_sequence) if current_user
-
       @list.more_topics_url = construct_url_with(:next, list_opts)
       @list.prev_topics_url = construct_url_with(:prev, list_opts)
       @rss = "tag"
diff --git a/app/models/category_list.rb b/app/models/category_list.rb
index 5c81c1a..306dfa3 100644
--- a/app/models/category_list.rb
+++ b/app/models/category_list.rb
@@ -1,16 +1,11 @@
 # frozen_string_literal: true
 
-class CategoryList
-  include ActiveModel::Serialization
-
+class CategoryList < DraftableList
   cattr_accessor :preloaded_topic_custom_fields
   self.preloaded_topic_custom_fields = Set.new
 
   attr_accessor :categories,
-                :uncategorized,
-                :draft,
-                :draft_key,
-                :draft_sequence
+                :uncategorized
 
   def initialize(guardian = nil, options = {})
     @guardian = guardian || Guardian.new
@@ -37,6 +32,8 @@ class CategoryList
         )
       end
     end
+
+    super(@guardian.user)
   end
 
   def preload_key
diff --git a/app/models/draftable_list.rb b/app/models/draftable_list.rb
new file mode 100644
index 0000000..3a641a7
--- /dev/null
+++ b/app/models/draftable_list.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+class DraftableList
+  include ActiveModel::Serialization
+
+  def initialize(user)
+    @current_user = user
+  end
+
+  def draft_key
+    @draft_key || Draft::NEW_TOPIC
+  end
+
+  def draft_sequence
+    @draft_sequence || DraftSequence.current(@current_user, draft_key)
+  end
+
+  def draft
+    @draft || Draft.get(@current_user, draft_key, draft_sequence) if @current_user
+  end
+
+  def draft_key=(key)
+    @draft_key = key
+  end
+
+  def draft_sequence=(sequence)
+    @draft_sequence = sequence
+  end
+
+  def draft=(draft)
+    @draft = draft
+  end
+end
diff --git a/app/models/topic_list.rb b/app/models/topic_list.rb
index d282cef..7dca128 100644
--- a/app/models/topic_list.rb
+++ b/app/models/topic_list.rb
@@ -1,8 +1,6 @@
 # frozen_string_literal: true
 
-class TopicList
-  include ActiveModel::Serialization
-
+class TopicList < DraftableList
   cattr_accessor :preloaded_custom_fields
   self.preloaded_custom_fields = Set.new
 
@@ -28,9 +26,6 @@ class TopicList
   attr_accessor(
     :more_topics_url,
     :prev_topics_url,
-    :draft,
-    :draft_key,
-    :draft_sequence,
     :filter,
     :for_period,
     :per_page,
@@ -57,6 +52,8 @@ class TopicList
     end
 
     @publish_read_state = !!@opts[:publish_read_state]
+
+    super(current_user)
   end
 
   def top_tags
diff --git a/lib/topic_list_responder.rb b/lib/topic_list_responder.rb
index c590e25..ca15ada 100644
--- a/lib/topic_list_responder.rb
+++ b/lib/topic_list_responder.rb
@@ -6,10 +6,6 @@ module TopicListResponder
   def respond_with_list(list)
     discourse_expires_in 1.minute
 
-    list.draft_key = Draft::NEW_TOPIC
-    list.draft_sequence = DraftSequence.current(current_user, Draft::NEW_TOPIC)
-    list.draft = Draft.get(current_user, list.draft_key, list.draft_sequence) if current_user
-
     respond_to do |format|
       format.html do
         @list = list
diff --git a/spec/models/category_list_spec.rb b/spec/models/category_list_spec.rb
index 8f3784f..d18abbe 100644
--- a/spec/models/category_list_spec.rb
+++ b/spec/models/category_list_spec.rb
@@ -237,5 +237,4 @@ describe CategoryList do
       end
     end
   end
-
 end
diff --git a/spec/requests/categories_controller_spec.rb b/spec/requests/categories_controller_spec.rb
index a2b9cea..6a60577 100644
--- a/spec/requests/categories_controller_spec.rb
+++ b/spec/requests/categories_controller_spec.rb
@@ -5,6 +5,7 @@ require 'rails_helper'
 describe CategoriesController do
   let(:admin) { Fabricate(:admin) }
   let!(:category) { Fabricate(:category, user: admin) }
+  fab!(:user) { Fabricate(:user) }
 
   context 'index' do
 
@@ -52,6 +53,26 @@ describe CategoriesController do
       expect(response.status).to eq(301)
       expect(response.body).to include(category.slug)
     end
+
+    it 'returns the right response for a normal user' do
+      sign_in(user)
+
+      Draft.set(user, Draft::NEW_TOPIC, 0, 'hello')
+
+      get "/categories.json"
+
+      expect(response.status).to eq(200)
+
+      category_list = response.parsed_body["category_list"]
+
+      expect(category_list["categories"].map { |c| c["id"] }).to contain_exactly(
+        SiteSetting.get(:uncategorized_category_id), category.id
+      )
+
+      expect(category_list["draft_sequence"]).to eq(0)
+      expect(category_list["draft_key"]).to eq(Draft::NEW_TOPIC)
+      expect(category_list["draft"]).to eq('hello')
+    end
   end
 
   context 'extensibility event' do
@@ -505,8 +526,19 @@ describe CategoriesController do
 
       get '/categories_and_latest.json'
       json = response.parsed_body
-      expect(json['category_list']['categories'].size).to eq(2) # 'Uncategorized' and category
-      expect(json['topic_list']['topics'].size).to eq(5)
+
+      category_list = json['category_list']
+      topic_list = json['topic_list']
+
+      expect(category_list['categories'].size).to eq(2) # 'Uncategorized' and category
+      expect(category_list['draft_key']).to eq(Draft::NEW_TOPIC)
+      expect(category_list['draft_sequence']).to eq(nil)
+      expect(category_list['draft']).to eq(nil)
+
+      expect(topic_list['topics'].size).to eq(5)
+      expect(topic_list['draft_key']).to eq(Draft::NEW_TOPIC)
+      expect(topic_list['draft_sequence']).to eq(nil)
+      expect(topic_list['draft']).to eq(nil)
 
       Fabricate(:category, parent_category: category)
 
diff --git a/spec/requests/tags_controller_spec.rb b/spec/requests/tags_controller_spec.rb
index 95714bc..15ad2d9 100644

[... diff too long, it was truncated ...]

GitHub sha: b979579c

Super small nitpick here, but why call it user here then current_user in the class?