DEV: Prefer tables over custom fields, commit topics, part 1 (#99)

DEV: Prefer tables over custom fields, commit topics, part 1 (#99)

This version still writes the data to custom fields for easier reversion, just in case.

diff --git a/app/controllers/discourse_code_review/code_review_controller.rb b/app/controllers/discourse_code_review/code_review_controller.rb
index 6bacaa0..a8517e6 100644
--- a/app/controllers/discourse_code_review/code_review_controller.rb
+++ b/app/controllers/discourse_code_review/code_review_controller.rb
@@ -153,18 +153,18 @@ module DiscourseCodeReview
       sha1 = params[:sha1]
 
       if sha1.present? && sha1.size >= 7
-        tcf = TopicCustomField
-          .where(name: DiscourseCodeReview::COMMIT_HASH)
-          .where("LEFT(LOWER(value), :len) = LOWER(:sha1)", len: sha1.size, sha1: sha1)
-          .order("created_at DESC")
-          .includes(:topic)
-          .first
+        topic =
+          Topic
+            .joins(:code_review_commit_topic)
+            .where("LEFT(LOWER(code_review_commit_topics.sha), :len) = LOWER(:sha1)", len: sha1.size, sha1: sha1)
+            .order("created_at DESC")
+            .first
       end
 
-      raise Discourse::NotFound.new if tcf.blank?
-      guardian.ensure_can_see!(tcf.topic)
+      raise Discourse::NotFound.new unless topic
+      guardian.ensure_can_see!(topic)
 
-      redirect_to tcf.topic.url
+      redirect_to topic.url
     end
 
     protected
diff --git a/app/models/commit_topic.rb b/app/models/commit_topic.rb
new file mode 100644
index 0000000..9f55ab8
--- /dev/null
+++ b/app/models/commit_topic.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+class DiscourseCodeReview::CommitTopic < ActiveRecord::Base
+  self.table_name = 'code_review_commit_topics'
+  belongs_to :topic
+end
diff --git a/db/migrate/20220111185242_create_code_review_commit_topics.rb b/db/migrate/20220111185242_create_code_review_commit_topics.rb
new file mode 100644
index 0000000..ac499e1
--- /dev/null
+++ b/db/migrate/20220111185242_create_code_review_commit_topics.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+class CreateCodeReviewCommitTopics < ActiveRecord::Migration[6.1]
+  def change
+    create_table :code_review_commit_topics, id: false do |t|
+      t.integer :topic_id, null: false, primary_key: true
+      t.text :sha, null: false
+      t.timestamps
+    end
+
+    add_index :code_review_commit_topics, :sha, unique: true
+
+    reversible do |dir|
+      dir.up do
+        execute <<~SQL
+          INSERT INTO code_review_commit_topics (topic_id, sha, created_at, updated_at)
+          SELECT
+            topics.id,
+            github_hashes.value,
+            github_hashes.created_at,
+            github_hashes.updated_at
+          FROM
+            (
+              SELECT *
+              FROM topic_custom_fields
+              WHERE name = 'commit hash'
+            ) github_hashes
+          INNER JOIN topics
+          ON github_hashes.topic_id = topics.id
+        SQL
+      end
+    end
+  end
+end
diff --git a/lib/discourse_code_review/github_pr_syncer.rb b/lib/discourse_code_review/github_pr_syncer.rb
index 022bb3a..339fb14 100644
--- a/lib/discourse_code_review/github_pr_syncer.rb
+++ b/lib/discourse_code_review/github_pr_syncer.rb
@@ -80,16 +80,8 @@ module DiscourseCodeReview
     def apply_github_approves(repo_name, commit_hash)
       topic =
         Topic
-          .where(
-            id:
-              TopicCustomField
-                .where(
-                  name: COMMIT_HASH,
-                  value: commit_hash
-                )
-                .limit(1)
-                .select(:topic_id)
-          )
+          .joins(:code_review_commit_topic)
+          .where(code_review_commit_topics: { sha: commit_hash })
           .first
 
       if topic
diff --git a/lib/discourse_code_review/rake_tasks.rb b/lib/discourse_code_review/rake_tasks.rb
index 4c25dda..1c1e17e 100644
--- a/lib/discourse_code_review/rake_tasks.rb
+++ b/lib/discourse_code_review/rake_tasks.rb
@@ -9,15 +9,7 @@ module DiscourseCodeReview
       end
 
       Rake::Task.define_task code_review_tag_commits: :environment do
-        topics =
-          Topic
-            .where(
-            id:
-            TopicCustomField
-          .select(:topic_id)
-          .where(name: DiscourseCodeReview::COMMIT_HASH)
-          )
-            .to_a
+        topics = Topic.joins(:code_review_commit_topic).to_a
 
           puts "Tagging #{topics.size} topics"
 
@@ -34,9 +26,9 @@ module DiscourseCodeReview
       Rake::Task.define_task code_review_full_sha_backfill: :environment do
         posts_with_commit = Post
           .joins("INNER JOIN topics ON topics.id = posts.topic_id")
-          .joins("INNER JOIN topic_custom_fields ON topics.id = topic_custom_fields.topic_id")
-          .includes(topic: :_custom_fields)
-          .where("topic_custom_fields.name = '#{DiscourseCodeReview::COMMIT_HASH}' AND
+          .joins("INNER JOIN code_review_commit_topics ON topics.id = code_review_commit_topics.topic_id")
+          .includes(topic: :code_review_commit_topic)
+          .where("
             topics.deleted_at IS NULL AND
             posts.deleted_at IS NULL AND
             posts.post_number = 1 AND
@@ -51,7 +43,7 @@ module DiscourseCodeReview
         posts_with_commit.find_each do |post_with_commit|
           puts "Replacing sha in post #{post_with_commit.id}..."
 
-          full_git_sha = post_with_commit.topic.custom_fields[DiscourseCodeReview::COMMIT_HASH]
+          full_git_sha = post_with_commit.topic.code_review_commit_topic.sha
           new_raw = post_with_commit.raw.gsub(/sha: [0-9a-f]{6,10}\b/, "sha: #{full_git_sha}")
 
           if new_raw == post_with_commit.raw
diff --git a/lib/discourse_code_review/state/commit_topics.rb b/lib/discourse_code_review/state/commit_topics.rb
index 7c6d53b..2d4fd7a 100644
--- a/lib/discourse_code_review/state/commit_topics.rb
+++ b/lib/discourse_code_review/state/commit_topics.rb
@@ -1,208 +1,214 @@
 # frozen_string_literal: true
 
-module DiscourseCodeReview::State::CommitTopics
-  class << self
-    def auto_link_commits(text, doc = nil)
-      linked_commits = find_linked_commits(text)
-      if (linked_commits.length > 0)
-        doc ||= Nokogiri::HTML5::fragment(PrettyText.cook(text, disable_emojis: true))
-        skip_tags = ["a", "code"]
-        linked_commits.each do |hash, topic|
-          doc.traverse do |node|
-            if node.text? && !skip_tags.include?(node.parent&.name)
-              node.replace node.content.gsub(hash, "<a href='#{topic.url}'>#{hash}</a>")
+module DiscourseCodeReview
+  module State::CommitTopics
+    class << self
+      def auto_link_commits(text, doc = nil)
+        linked_commits = find_linked_commits(text)
+        if (linked_commits.length > 0)
+          doc ||= Nokogiri::HTML5::fragment(PrettyText.cook(text, disable_emojis: true))
+          skip_tags = ["a", "code"]
+          linked_commits.each do |hash, topic|
+            doc.traverse do |node|
+              if node.text? && !skip_tags.include?(node.parent&.name)
+                node.replace node.content.gsub(hash, "<a href='#{topic.url}'>#{hash}</a>")
+              end
             end
+            text = HtmlToMarkdown.new(doc.to_html).to_markdown
           end
-          text = HtmlToMarkdown.new(doc.to_html).to_markdown
         end
+        [text, linked_commits, doc]
       end
-      [text, linked_commits, doc]
-    end
 
-    def detect_shas(text)
-      text.scan(/(?:[^a-zA-Z0-9]|^)([a-f0-9]{8,})(?:[^a-zA-Z0-9]|$)/).flatten
-    end
+      def detect_shas(text)
+        text.scan(/(?:[^a-zA-Z0-9]|^)([a-f0-9]{8,})(?:[^a-zA-Z0-9]|$)/).flatten
+      end
 
-    def ensure_commit_comment(user:, topic_id:, comment:)
-      context = ""
-      if comment[:line_content]
-        context = <<~MD
-          [quote]
-          #{comment[:path]}
+      def ensure_commit_comment(user:, topic_id:, comment:)
+        context = ""
+        if comment[:line_content]
+          context = <<~MD
+            [quote]
+            #{comment[:path]}
 
-          `‍``diff
-          #{comment[:line_content]}
-          `‍``
+            `‍``diff

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

GitHub sha: e9bcd14cf9ab7123f93279ce24f5f332b8122b77

This commit appears in #99 which was approved by eviltrout. It was merged by danielwaterworth.