DEV: fix 'posts:reorder' rake task

DEV: fix ‘posts:reorder’ rake task

Running the reorder rake task was triggering the following error:

PG::UniqueViolation: ERROR: duplicate key value violates unique constraint “post_timings_unique”

I re-worked the queries and refactored to use the same couple of queries for all similar tables/columns.

diff --git a/lib/tasks/posts.rake b/lib/tasks/posts.rake
index 0515f43..a491497 100644
--- a/lib/tasks/posts.rake
+++ b/lib/tasks/posts.rake
@@ -310,92 +310,77 @@ end
 desc 'Reorders all posts based on their creation_date'
 task 'posts:reorder_posts', [:topic_id] => [:environment] do |_, args|
   Post.transaction do
-    # update sort_order and flip post_number to prevent
-    # unique constraint violations when updating post_number
-    builder = DB.build(<<~SQL)
+
+    builder = DB.build <<~SQL
       WITH ordered_posts AS (
-          SELECT
-            id,
-            ROW_NUMBER()
-            OVER (
-              PARTITION BY topic_id
-              ORDER BY created_at, post_number ) AS new_post_number
-          FROM posts
-          /*where*/
+        SELECT
+          id,
+          ROW_NUMBER() OVER (
+            PARTITION BY
+              topic_id
+            ORDER BY
+              created_at,
+              post_number
+          ) AS new_post_number
+        FROM
+          posts
+        /*where*/
       )
-      UPDATE posts AS p
-      SET sort_order = o.new_post_number,
-        post_number  = p.post_number * -1
-      FROM ordered_posts AS o
-      WHERE p.id = o.id AND
-            p.post_number <> o.new_post_number
+      UPDATE
+        posts AS p
+      SET
+        sort_order = o.new_post_number,
+        post_number = p.post_number * -1
+      FROM
+        ordered_posts AS o
+      WHERE
+        p.id = o.id AND
+        p.post_number <> o.new_post_number
     SQL
+
     builder.where("topic_id = :topic_id") if args[:topic_id]
     builder.exec(topic_id: args[:topic_id])
 
-    DB.exec(<<~SQL)
-      UPDATE notifications AS x
-      SET post_number = p.sort_order
-      FROM posts AS p
-      WHERE x.topic_id = p.topic_id AND
-            x.post_number = ABS(p.post_number) AND
-            p.post_number < 0
-    SQL
-
-    DB.exec(<<~SQL)
-      UPDATE post_timings AS x
-      SET post_number = x.post_number * -1
-      FROM posts AS p
-      WHERE x.topic_id = p.topic_id AND
-            x.post_number = ABS(p.post_number) AND
-            p.post_number < 0;
-
-      UPDATE post_timings AS t
-      SET post_number = p.sort_order
-      FROM posts AS p
-      WHERE t.topic_id = p.topic_id AND
-            t.post_number = p.post_number AND
-            p.post_number < 0;
-    SQL
-
-    DB.exec(<<~SQL)
-      UPDATE posts AS x
-      SET reply_to_post_number = p.sort_order
-      FROM posts AS p
-      WHERE x.topic_id = p.topic_id AND
-            x.reply_to_post_number = ABS(p.post_number) AND
-            p.post_number < 0;
-    SQL
+    [
+      ["notifications", "post_number"],
+      ["post_timings", "post_number"],
+      ["posts", "reply_to_post_number"],
+      ["topic_users", "last_read_post_number"],
+      ["topic_users", "highest_seen_post_number"],
+      ["topic_users", "last_emailed_post_number"],
+    ].each do |table, column|
+      DB.exec <<~SQL
+        UPDATE
+          #{table} AS x
+        SET
+          #{column} = p.sort_order * -1
+        FROM
+          posts AS p
+        WHERE
+          p.post_number < 0 AND
+          x.topic_id = p.topic_id AND
+          x.#{column} = ABS(p.post_number)
+      SQL
+
+      DB.exec <<~SQL
+        UPDATE
+          #{table}
+        SET
+          #{column} = #{column} * -1
+        WHERE
+          #{column} < 0
+      SQL
+    end
 
-    DB.exec(<<~SQL)
-      UPDATE topic_users AS x
-        SET last_read_post_number = p.sort_order
-      FROM posts AS p
-      WHERE x.topic_id = p.topic_id AND
-            x.last_read_post_number = ABS(p.post_number) AND
-            p.post_number < 0;
-
-      UPDATE topic_users AS x
-        SET highest_seen_post_number = p.sort_order
-      FROM posts AS p
-      WHERE x.topic_id = p.topic_id AND
-            x.highest_seen_post_number = ABS(p.post_number) AND
-            p.post_number < 0;
-
-      UPDATE topic_users AS x
-        SET last_emailed_post_number = p.sort_order
-      FROM posts AS p
-      WHERE x.topic_id = p.topic_id AND
-            x.last_emailed_post_number = ABS(p.post_number) AND
-            p.post_number < 0;
+    DB.exec <<~SQL
+      UPDATE
+        posts
+      SET
+        post_number = sort_order
+      WHERE
+        post_number < 0
     SQL
 
-    # finally update the post_number
-    DB.exec(<<~SQL)
-      UPDATE posts
-      SET post_number = sort_order
-      WHERE post_number < 0
-    SQL
   end
 
   puts "", "Done.", ""

GitHub sha: 712ab33f