如果它们属于同一用户,如何将流中的项目组合在一起

时间:2010-07-04 00:04:09

标签: ruby-on-rails

我有一个属于用户的活动流(Activity)和一个created_at。我想介绍一下10项最新活动,并提出我想要将活动分组在一起的警告。我知道我可以使用group_by,但我不希望用户将所有内容组合在一起,只有那些出现的活动>连续2次。

  • 汤姆说了些什么
  • 乔做了一些事
  • 乔踢了一些东西
  • 乔打了一些东西
  • 乔说了些什么
  • 比尔做了一些事
  • 比尔送了一些东西

如果它被分组,那就是这样:

  • 汤姆说了些什么
  • 乔做了一些事
  • 乔踢了一些东西[更多来自乔...]
  • 比尔做了一些事
  • 比尔送了一些东西

更多链接会打开一个隐藏的div。

2 个答案:

答案 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,并继续循环,直到超过您的阈值。