我有一个与通知模式有has_many
关系的用户模式,其notifier_id
属性等于某些User.id
我尝试编写一些逻辑来获取已向某个用户发送通知的每个用户的最新通知列表,但我对最佳方法感到困惑。
我试过了:
@notifications = @user.notifications.uniq { |note| note.notifier_id }
但是它给了我所有现有的通知,没有过滤。
我找到一篇关于类似问题的SO帖子,其解决方案与此类似:
@notifications = @user.notifications.map { |note| note.notifier_id }
.uniq
.map{ |notifier_id| Notification.find(notifier_id) }
但这对我没有用,因为有许多通知具有相同的notifier_id
我能想到的唯一另一个选择是循环遍历所有User.notifications,将每个唯一notifier_id
添加到一个数组,然后使用该数组构建另一个数组,只包含来自每个唯一通知程序的第一个通知,但我觉得应该有更好的方法来做到这一点。有吗?
更新:
这是生成的SQL:@user.notifications.select("DISTINCT notifications.notifier_id")
SELECT DISTINCT notifications.notifier_id FROM "notifications" WHERE "notifications"."user_id" = $1 ORDER BY "notifications"."created_at" DESC
更新:
这是我改编的解决方案:
inner = Notification.
order(nil).
select("DISTINCT notifications.notifier_id, notifications.*").
where("notifications.user_id = ?", @user.id)
@notifications = Notification.from("(#{inner.to_sql}) notifications").
order("notifications.created_at DESC")
这是它的SQL:
Notification Load (3.3ms) SELECT "notifications".* FROM (SELECT DISTINCT notifications.notifier_id, notifications.* FROM "notifications" WHERE (notifications.user_id = 313) ORDER BY "notifications"."created_at" DESC) notifications ORDER BY "notifications"."created_at" DESC, notifications.created_at DESC
输出与@ user.notifications
相同临时解决方案:
这可以实现我想要的,但我想使用SQL查询
notifiers = []
@user.notifications.each do |note|
if note.notifier_id
found = false
notifiers.each do |notifier_id|
if notifier_id == note.notifier_id
found = true
break
end
end
if !found
notifiers << note.notifier_id
end
end
end
notifiers.each do |notifier_id|
@notifications << @user.notifications.find{|x| x.notifier_id == notifier_id}
end
答案 0 :(得分:0)
使用DISTINCT
根据notifier_id
选择所有唯一身份通知。
inner = Notification.
order(nil).
select("DISTINCT notifications.notifier_id, notifications.*").
where("notifications.user_id = ?", current_user.id)
Notification.from("(#{inner.to_sql}) notifications").
order("notifications.created_at DESC")