ActiveRecord PSQL按最近的created_at of has_many association + pagination

时间:2016-11-21 20:13:22

标签: ruby-on-rails postgresql activerecord pagination kaminari

从标题开始,我想显示一个用户列表 - 按最近创建的has_many关联进行排序。

User
  has_many :interactions

我需要能够显示一个包含用户的表 - 按其最后interaction日期排序,该表还应显示交互的总数(不使用数据库中的counter_cache) ,还包括分页。

我们之前使用的(不工作)范围是User.with_a_bunch_of_scopes.includes(:interactions).order("interactions.created_at DESC") 我删除了大多数尝试,但我尝试使用MAX(interactions.created_at)并按其他各种属性进行分组,但无济于事。

分页是这里的难点 - 似乎,除非我搞砸了一些事情,否则使用:includes / LEFT OUTER JOIN正确地限制每个交互只有一个用户,但是,似乎是其他互动的范围。我使用了Kaminari gem,但能够使用limitoffset

复制问题

例如:

Interaction Users sorted_by interactions.created_at
-------------------------
User 1
User 1
User 2
User 3
User 2
User 2
User 4
User 1
User 4
User 3
User 5

给我们:

Page # per 4
Page 1 - [1, 2, 3, 4]
Page 2 - [2, 4, 1, 3]
Page 3 - [4, 3, 5]

我们期望它是:

Page # per 4
Page 1 - [1, 2, 3, 4]
Page 2 - [5]

它恰好只包含每个用户一次,但是,当用户已经包含在以前的页面中时,它会包括用户。

非常感谢任何帮助。一直在回到这个问题,然后尝试解决它一段时间,并且永远无法按预期返回。

1 个答案:

答案 0 :(得分:0)

假设您需要一组用户对象,并且由于您为每个用户动态生成交互计数,您可以通过为所有用户的每个唯一用户映射as_json来执行此操作(以及分页)已排序的互动:

User.includes(:interactions).order('interactions.created_at desc').uniq.page(params[:page]).per(4).map(&:as_json)

要使map(&:as_json)工作,您需要覆盖用户模型中的as_json方法,并包含计算交互计数的方法。例如:

def as_json(_opts={})
  super(_opts.merge({
    methods: [ :interactions_count ]
  }))
end

def interactions_count
  interactions.size
end

这应该为您提供一系列用户对象,包括其交互计数。如果您只是在寻找用户ID,那么您可以这样做:

User.includes(:interactions).order('interactions.created_at desc').uniq.page(params[:page]).per(4).pluck(:id)

希望这有帮助!