ActiveRecord has two methods to remove duplicates. Method uniq and option distinct: true in method count. I thought uniq.count and count(distinct: true) were identical. Indeed, uniq.count still counts duplicates, and count(distinct: true) must be used here.
In simple words, use uniq to get unique result set, use count(distinct: true) to count unique result.
For example, user has many activities, and I want to get all users having a specific type of activities:
users = User.joins(:activities).where(
activities: { activity_type: 'purchase'}
)
Because a user may have multiple activities with the same type, the result above may contain duplicate users. Method uniq can be used here to remove the duplicates:
users = users.uniq
But users.uniq.count generates SQL like below:
SELECT DISTINCT COUNT(*) ...
This SQL counts all records with duplicates, and apply DISTINCT on the count, which has only one row. So DISTINCT has no effect here.
On the other hand, users.count(distinct: true) generates SQL below, which removes duplicates first, then count the result.
SELECT COUNT(DISTINCT users.id) ...