我有一个属于用户的活动流(Activity)和一个created_at。我想介绍一下10项最新活动,并提出我想要将活动分组在一起的警告。我知道我可以使用group_by,但我不希望用户将所有内容组合在一起,只有那些出现的活动>连续2次。
如果它被分组,那就是这样:
更多链接会打开一个隐藏的div。
答案 0 :(得分:1)
答案 1 :(得分:0)
我认为没有任何特殊方法可以做到这一点。你必须这样做。
假设您可以有效地抓取所有活动及其相关用户。你可能无法有效地做到这一点,对于像网站上的活动那样频繁的事情,但假设你可以说,为了简单起见,你可以这样做。
您想要的是迭代您的活动,并收集您想要显示的行。简而言之,简单的道路就是Activity
模型上的一个类似于finder的方法,它会返回用户连续动作的数组。
将您的阈值留给视图。 (连续动作不超过2次,总共不超过10行。)
如果Ruby有一些从数组中收集连续元素的奇特方法,那么我可能会看起来很愚蠢,但这里有一些(未经测试的)代码:
class Activity < ActiveRecord::Base
belongs_to :user
def self.each_consecutive_group(options={})
default_options = { :order => 'created_at DESC' }
current_group = nil
last_user_id = false
self.all(default_options.merge(options)).each do |activity|
# Look for consecutive activities from the same user.
# (This is never true on the first iteration.)
if last_user_id == activity.user_id
current_group << activity
else
# The nil case happens during first iteration.
yield current_group unless current_group.nil?
# Initialize state for the next group of activities.
current_group = [activity]
last_user_id = activity.user_id
end
end
# Do we still have something to yield?
yield current_group if current_group
end
# Just return the above as an array, rather than iterating.
def self.consecutive_groups(options={})
groups = []
self.each_consecutive_group(options) { |group| groups << group }
groups
end
end
# Usage:
Activity.each_grouped(:include => :user, :limit => 30) do |group|
# [...]
end
# Or if you want to pass something from the controller to the view:
@activity_groups = Activity.grouped(:include => :user, :limit => 30)
为了缓解性能问题,我只需要保证安全。如果您想要10行,您可以选择20个活动范围进行搜索,并且可以隐藏10个记录。更多,你可能会看到不到10行。选择20条记录并不是很多,你可以选择扩大这个数字。
如果你在总是显示10行时顽固不化,那么你可能必须将阈值代码移到上面的任何方式。然后,您可以使用find_in_batches
而不是:limit
,并继续循环,直到超过您的阈值。