class AddUserBadgeUniqueIndex < ActiveRecord::Migration def up # used to keep badges distinct add_column :user_badges, :seq, :integer, default: 0, null: false # invent artificial seq for badges execute " UPDATE user_badges ub1 SET seq = X.seq FROM ( SELECT ub.id, rank() OVER (PARTITION BY user_id ORDER BY granted_at) seq FROM user_badges ub JOIN badges b ON b.id = ub.badge_id WHERE b.multiple_grant ) X WHERE ub1.id = X.id " # delete all single award dupes execute " DELETE FROM user_badges ub1 WHERE ub1.id NOT IN ( SELECT MIN(ub.id) FROM user_badges ub GROUP BY ub.user_id, ub.badge_id, ub.seq ) " add_index :user_badges, [:badge_id, :user_id, :seq], unique: true, where: 'post_id IS NULL' end def down remove_column :user_badges, :seq, :integer end end