DEV: Move user syncing to its own module

DEV: Move user syncing to its own module

diff --git a/lib/discourse_code_review/github_user_syncer.rb b/lib/discourse_code_review/github_user_syncer.rb
new file mode 100644
index 0000000..06c02c7
--- /dev/null
+++ b/lib/discourse_code_review/github_user_syncer.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+module DiscourseCodeReview
+  class GithubUserSyncer
+    def ensure_user(name:, email: nil, github_login: nil, github_id: nil)
+      user = nil
+
+      user ||=
+        if github_id
+            User.find_by(
+              id:
+                UserCustomField
+                  .select(:user_id)
+                  .where(name: GithubId, value: github_id)
+                  .limit(1)
+            )
+        end
+
+      user ||=
+        if github_login
+          user =
+            User.find_by(
+              id:
+                UserCustomField
+                  .select(:user_id)
+                  .where(name: GithubLogin, value: github_login)
+                  .limit(1)
+            )
+        end
+
+      user ||= begin
+        email ||= email_for(github_login)
+
+        User.find_by_email(email)
+      end
+
+      user ||= begin
+        username = UserNameSuggester.sanitize_username(github_login || name)
+
+        User.create!(
+          email: email,
+          username: UserNameSuggester.suggest(username.presence || email),
+          name: name.presence || User.suggest_name(email),
+          staged: true
+        )
+      end
+
+      if github_login
+        rel = UserCustomField.where(name: GithubLogin, value: github_login)
+        existing = rel.pluck(:user_id)
+
+        if existing != [user.id]
+          rel.destroy_all
+          UserCustomField.create!(name: GithubLogin, value: github_login, user_id: user.id)
+        end
+      end
+
+      if github_id
+
+        rel = UserCustomField.where(name: GithubId, value: github_id)
+        existing = rel.pluck(:user_id)
+
+        if existing != [user.id]
+          rel.destroy_all
+          UserCustomField.create!(name: GithubId, value: github_id, user_id: user.id)
+        end
+      end
+      user
+    end
+
+    private
+
+    def email_for(github_login)
+      "#{github_login}@fake.github.com"
+    end
+  end
+end
diff --git a/lib/discourse_code_review/importer.rb b/lib/discourse_code_review/importer.rb
index 6a672cf..586861e 100644
--- a/lib/discourse_code_review/importer.rb
+++ b/lib/discourse_code_review/importer.rb
@@ -118,7 +118,7 @@ module DiscourseCodeReview
 
       raw = "[excerpt]\n#{body}\n[/excerpt]\n\n`‍``diff\n#{diff}\n#{truncated_message}`‍``\n#{link} #{short_hash}"
 
-      user = ensure_user(
+      user = DiscourseCodeReview.github_user_syncer.ensure_user(
         email: commit[:email],
         name: commit[:name],
         github_login: commit[:author_login],
@@ -178,59 +178,6 @@ module DiscourseCodeReview
       end
     end
 
-    def ensure_user(email:, name:, github_login: nil, github_id: nil)
-      user = nil
-
-      if github_id
-        if user_id = UserCustomField.where(name: DiscourseCodeReview::GithubId, value: github_id).pluck(:user_id).first
-          user = User.find_by(id: user_id)
-        end
-      end
-
-      if !user && github_login
-        if user_id = UserCustomField.where(name: DiscourseCodeReview::GithubLogin, value: github_login).pluck(:user_id).first
-          user = User.find_by(id: user_id)
-        end
-      end
-
-      user ||= User.find_by_email(email)
-
-      if !user
-        username = UserNameSuggester.sanitize_username(github_login || name)
-        begin
-          user = User.create!(
-            email: email,
-            username: UserNameSuggester.suggest(username.presence || email),
-            name: name.presence || User.suggest_name(email),
-            staged: true
-          )
-        end
-      end
-
-      if github_login
-
-        rel = UserCustomField.where(name: DiscourseCodeReview::GithubLogin, value: github_login)
-        existing = rel.pluck(:user_id)
-
-        if existing != [user.id]
-          rel.destroy_all
-          UserCustomField.create!(name: DiscourseCodeReview::GithubLogin, value: github_login, user_id: user.id)
-        end
-      end
-
-      if github_id
-
-        rel = UserCustomField.where(name: DiscourseCodeReview::GithubId, value: github_id)
-        existing = rel.pluck(:user_id)
-
-        if existing != [user.id]
-          rel.destroy_all
-          UserCustomField.create!(name: DiscourseCodeReview::GithubId, value: github_id, user_id: user.id)
-        end
-      end
-      user
-    end
-
     protected
 
     def import_comment(comment)
@@ -241,7 +188,7 @@ module DiscourseCodeReview
       # do we have the commit?
       if topic_id = TopicCustomField.where(name: DiscourseCodeReview::CommitHash, value: comment[:commit_hash]).pluck(:topic_id).first
         login = comment[:login] || "unknown"
-        user = ensure_user(email: "#{login}@fake.github.com", name: login, github_login: login)
+        user = DiscourseCodeReview.github_user_syncer.ensure_user(name: login, github_login: login)
 
         context = ""
         if comment[:line_content]
diff --git a/plugin.rb b/plugin.rb
index 10ecbf7..b04c369 100644
--- a/plugin.rb
+++ b/plugin.rb
@@ -79,6 +79,10 @@ after_initialize do
       Octokit::Client.new
     end
 
+    def self.github_user_syncer
+      @github_user_syncer ||= GithubUserSyncer.new
+    end
+
     def self.sync_post_to_github(client, post)
       topic = post.topic
       hash = topic&.custom_fields[DiscourseCodeReview::CommitHash]
@@ -111,6 +115,7 @@ after_initialize do
   end
 
   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/importer.rb", __FILE__)
   require File.expand_path("../lib/discourse_code_review/github_repo.rb", __FILE__)

GitHub sha: 66d17ae8

We usually write constants in Ruby in “UPPER_SNAKE_CASE” (eg. GITHUB_ID).

“PascalCase” is usually for module/class names.

Can’t all of this be done in 1 SQL query?

Ditto here. Possible in 1 SQL query instead?

I didn’t change this code, I just moved it.