You can't do this reliably through the usual ActiveRecord interface but you can do it through SQL using a window function. You want some SQL like this:
select id, user_id, group_id, created_at
from (
select id, user_id, group_id, created_at,
row_number() over (partition by group_id order by created_at desc, id desc) as r
from user_pulses
where user_id = :user_id
) dt
where r = 1
and then wrap that in find_by_sql
:
pulses = UserPulses.find_by_sql([%q{
select id, user_id, group_id, created_at
from (
select id, user_id, group_id, created_at,
row_number() over (partition by group_id order by created_at desc, id desc) as r
from user_pulses
where user_id = :user_id
) dt
where r = 1
}, :user_id => user.id])
The window function part essentially does a local GROUP BY with each group_id
, sorts them (with id desc
as the secondary sort key as a "just in case" tie breaker), and tacks the per-group row number in r
. Then the outer query filters out the first in each group (where r = 1
)and peels off the original
user_pulses` columns.