DEV: Move category creation into its own module

DEV: Move category creation into its own module

diff --git a/lib/discourse_code_review/github_category_syncer.rb b/lib/discourse_code_review/github_category_syncer.rb
new file mode 100644
index 0000000..1e16edc
--- /dev/null
+++ b/lib/discourse_code_review/github_category_syncer.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+module DiscourseCodeReview
+  module GithubCategorySyncer
+    GithubRepoName = "GitHub Repo Name"
+
+    class << self
+      def ensure_category(repo_name:)
+        Category.transaction(requires_new: true) do
+          category =
+            Category.where(
+              id:
+                CategoryCustomField
+                  .select(:category_id)
+                  .where(name: GithubRepoName, value: repo_name)
+            ).first
+
+          if category.nil?
+            short_name = find_category_name(repo_name.split("/", 2).last)
+
+            category =
+              Category.create!(
+                name: short_name,
+                user: Discourse.system_user
+              )
+
+            category.custom_fields[GithubRepoName] = repo_name
+            category.save_custom_fields
+          end
+
+          category
+        end
+      end
+
+      def each_repo_name(&blk)
+        CategoryCustomField
+          .where(name: GithubRepoName)
+          .pluck(:value)
+          .each(&blk)
+      end
+
+      private
+
+      def find_category_name(name)
+        if Category.where(name: name).exists?
+          name += SecureRandom.hex
+        else
+          name
+        end
+      end
+    end
+  end
+end
diff --git a/lib/discourse_code_review/importer.rb b/lib/discourse_code_review/importer.rb
index 586861e..097df69 100644
--- a/lib/discourse_code_review/importer.rb
+++ b/lib/discourse_code_review/importer.rb
@@ -4,15 +4,13 @@ module DiscourseCodeReview
   class Importer
     attr_reader :github_repo
 
-    GithubRepoName = "GitHub Repo Name"
-
     def initialize(github_repo)
       @github_repo = github_repo
     end
 
     def self.import_commit(sha)
       client = DiscourseCodeReview.octokit_client
-      CategoryCustomField.where(name: GithubRepoName).pluck(:value).each do |repo_name|
+      GithubCategorySyncer.each_repo_name do |repo_name|
         repo = GithubRepo.new(repo_name, client)
         importer = Importer.new(repo)
 
@@ -27,21 +25,9 @@ module DiscourseCodeReview
 
     def category_id
       @category_id ||=
-        begin
-          id = Category.where(<<~SQL, name: GithubRepoName, value: github_repo.name).order(:id).pluck(:id).first
-            id IN (SELECT category_id FROM category_custom_fields WHERE name = :name AND value = :value)
-          SQL
-          if !id
-            Category.transaction do
-              short_name = find_category_name(github_repo.name.split("/").last)
-              category = Category.create!(name: short_name, user: Discourse.system_user)
-              category.custom_fields[GithubRepoName] = github_repo.name
-              category.save_custom_fields
-              id = category.id
-            end
-          end
-          id
-        end
+        GithubCategorySyncer.ensure_category(
+          repo_name: github_repo.name
+        ).id
     end
 
     def import_commits
@@ -219,13 +205,5 @@ module DiscourseCodeReview
         )
       end
     end
-
-    def find_category_name(name)
-      if Category.where(name: name).exists?
-        name += SecureRandom.hex
-      else
-        name
-      end
-    end
   end
 end
diff --git a/plugin.rb b/plugin.rb
index b04c369..59f6da0 100644
--- a/plugin.rb
+++ b/plugin.rb
@@ -94,7 +94,7 @@ after_initialize do
           path = fields[DiscourseCodeReview::CommentPath]
           position = fields[DiscourseCodeReview::CommentPosition]
 
-          if repo = post.topic.category.custom_fields[DiscourseCodeReview::Importer::GithubRepoName]
+          if repo = post.topic.category.custom_fields[DiscourseCodeReview::GithubCategorySyncer::GithubRepoName]
             post_user_name = user.name || user.username
 
             github_post_contents = [
@@ -116,6 +116,7 @@ after_initialize do
 
   require File.expand_path("../app/controllers/discourse_code_review/code_review_controller.rb", __FILE__)
   require File.expand_path("../lib/discourse_code_review/github_user_syncer.rb", __FILE__)
+  require File.expand_path("../lib/discourse_code_review/github_category_syncer.rb", __FILE__)
   require File.expand_path("../lib/discourse_code_review/importer.rb", __FILE__)
   require File.expand_path("../lib/discourse_code_review/github_repo.rb", __FILE__)
 
diff --git a/spec/plugin_spec.rb b/spec/plugin_spec.rb
index 2649e6f..d46a383 100644
--- a/spec/plugin_spec.rb
+++ b/spec/plugin_spec.rb
@@ -28,7 +28,7 @@ describe DiscourseCodeReview do
     context 'when a category, topic and post exist with appropriate custom fields, a reply and another post have been created and sync_to_github is true' do
       fab!(:category) do
         Fabricate(:category).tap do |category|
-          category.custom_fields[DiscourseCodeReview::Importer::GithubRepoName] = 'some github repo'
+          category.custom_fields[DiscourseCodeReview::GithubCategorySyncer::GithubRepoName] = 'some github repo'
           category.save_custom_fields
         end
       end

GitHub sha: 25c242f2

Constants in Ruby are in “UPPER_SNAKE_CASE”