diff --git a/app/models/user_badge.rb b/app/models/user_badge.rb index 61cd45436af..82f5555e9a8 100644 --- a/app/models/user_badge.rb +++ b/app/models/user_badge.rb @@ -18,14 +18,31 @@ class UserBadge < ActiveRecord::Base Badge.decrement_counter 'grant_count', self.badge_id end + # Make sure we don't have duplicate badges. def self.ensure_consistency! - dup_ids = [] - # Single grant badges shouldn't have duplicates at all. - dup_ids += exec_sql("SELECT u1.id FROM user_badges u1, user_badges u2, badges WHERE u1.badge_id = badges.id AND u1.user_id = u2.user_id AND u1.badge_id = u2.badge_id AND (NOT badges.multiple_grant) AND u1.granted_at > u2.granted_at").to_a - # Multiple grant badges can have duplicates but not with the same post_ids. - dup_ids += exec_sql("SELECT u1.id FROM user_badges u1, user_badges u2, badges WHERE u1.badge_id = badges.id AND u1.user_id = u2.user_id AND u1.badge_id = u2.badge_id AND badges.multiple_grant AND u1.post_id = u2.post_id AND u1.granted_at > u2.granted_at").to_a - dup_ids = dup_ids.map {|x| x["id"].to_i } + dup_ids = exec_sql("SELECT u1.id + FROM user_badges u1, user_badges u2, badges + WHERE u1.badge_id = badges.id + AND u1.user_id = u2.user_id + AND u1.badge_id = u2.badge_id + AND (NOT badges.multiple_grant) + AND u1.granted_at > u2.granted_at + LIMIT 1000").to_a + + dup_ids << exec_sql("SELECT u1.id + FROM user_badges u1, user_badges u2, badges + WHERE u1.badge_id = badges.id + AND u1.user_id = u2.user_id + AND u1.badge_id = u2.badge_id + AND badges.multiple_grant + AND u1.post_id = u2.post_id + AND u1.granted_at > u2.granted_at + LIMIT 1000").to_a + + dup_ids.flatten! + dup_ids.map! {|row| row['id'].to_i } + dup_ids.uniq! UserBadge.where(id: dup_ids).destroy_all end end