FIX: ensure wiki editor is assigned consistently

FIX: ensure wiki editor is assigned consistently

DISTINCT ON was not providing stability, this ensures the backfill will be stable on a specific post avoiding risk around double grants.

diff --git a/lib/badge_queries.rb b/lib/badge_queries.rb
index 1c42e99..8348087 100644
--- a/lib/badge_queries.rb
+++ b/lib/badge_queries.rb
@@ -103,12 +103,18 @@ module BadgeQueries
   SQL
 
   WikiEditor = <<~SQL
-    SELECT DISTINCT ON (pr.user_id) pr.user_id, pr.post_id, pr.created_at granted_at
-    FROM post_revisions pr
-    JOIN badge_posts p on p.id = pr.post_id
-    WHERE p.wiki
-        AND NOT pr.hidden
-        AND (:backfill OR p.id IN (:post_ids))
+    SELECT pr2.user_id, pr2.post_id, pr2.created_at granted_at
+    FROM
+    (
+      SELECT min(pr.id) id
+      FROM post_revisions pr
+      JOIN badge_posts p on p.id = pr.post_id
+      WHERE p.wiki
+          AND NOT pr.hidden
+          AND (:backfill OR p.id IN (:post_ids))
+      GROUP BY pr.user_id
+    ) as X
+    JOIN post_revisions pr2 ON pr2.id = X.id
   SQL
 
   Welcome = <<~SQL
diff --git a/spec/models/badge_spec.rb b/spec/models/badge_spec.rb
index bd1639a..221569d 100644
--- a/spec/models/badge_spec.rb
+++ b/spec/models/badge_spec.rb
@@ -3,13 +3,6 @@
 require 'rails_helper'
 
 describe Badge do
-  it { is_expected.to belong_to(:badge_type) }
-  it { is_expected.to belong_to(:badge_grouping) }
-  it { is_expected.to have_many(:user_badges).dependent(:destroy) }
-
-  it { is_expected.to validate_presence_of(:name) }
-  it { is_expected.to validate_presence_of(:badge_type) }
-  it { is_expected.to validate_uniqueness_of(:name) }
 
   it 'has a valid system attribute for new badges' do
     expect(Badge.create!(name: "test", badge_type_id: 1).system?).to be false
@@ -151,6 +144,21 @@ describe Badge do
     end
   end
 
+  context "WikiEditor badge" do
+
+    it "is awarded" do
+      wiki_editor_badge = Badge.find(Badge::WikiEditor)
+      post = Fabricate(:post, wiki: true)
+      revisor = PostRevisor.new(post)
+      revisor.revise!(post.user, { raw: "I am editing a wiki" }, force_new_version: true)
+
+      BadgeGranter.backfill(wiki_editor_badge)
+
+      expect(UserBadge.where(user_id: post.user.id, badge_id: Badge::WikiEditor).count).to eq(1)
+    end
+
+  end
+
   context "PopularLink badge" do
 
     let(:popular_link_badge) do

GitHub sha: 40b6e278

This commit has been mentioned on Discourse Meta. There might be relevant details there:

https://meta.discourse.org/t/wiki-editor-badge-is-awarded-multiple-times/134205/9