Rails - group_by

8

我的应用程序有一些报表,我正在尝试为所有这些集合制作一个 group_by 的辅助方法。

例如:

def group_collection(collection, options = {})
    column = options[:column]
    group_count = collection.group_by{ |item| item.column.strftime('%b %y')}
end

这是我计划使用它的方式。
@user_groups = group_collection(@users, :column => "created_at")

很遗憾,这并不起作用。
undefined method `column' for... [CollectionObject]

有什么方法可以在运行时将“column”变量转换为实际的列类型,使其被视为activerecord列而不是实例方法?
2个回答

22

忽略你代码中的其他问题,你想要使用column实现的功能可以如下实现:

collection.group_by { |item| item.send(column).strftime('%b %y') }
这段代码有效是因为在Ruby中,访问实例变量的方式是通过访问器方法,通常以要访问的变量命名,因此@item.foobar会在@item上调用foobar方法。
现在,回到那些“其他问题”。很好,你试图将重复的行为移到一个地方,并且这表明你在考虑可扩展性时会使事情变得不太明确而更具灵活性。但是,有几件事情在这里不会很好处理,我觉得必须指出来。
1.分组适用于许多数据类型,其中大多数不响应strftime。通过硬编码调用它,您正在引入意外行为,这意味着您无法运行group_collection(@users, :column => 'phone_number')。相反,在测试列数据能否响应它后再执行该操作。
collection.group_by do |item|
  data = item.send(column)
  data.respond_to?(:strftime) ? data.strftime('%b %y') : data
end
如果你确定这个助手方法的行为是根据任意一列进行分组的,那么你可以放弃接受选项哈希的额外复杂性,只需绕过它即可。
def group_by_column(collection, column)
  collection.group_by { ... }
end
group_by_column(@users, :column)
  • 如果你正在使用 Ruby 1.9+ 并且不需要进行任何额外的格式化,那么你可以更轻松地按任意列进行分组。

  • @users.group_by &:created_at
    

    谢谢,那个有效。你在代码中还看到什么其他问题吗?我还需要等待另外7分钟才能将其标记为已回答。 :) - AMIT
    更新了“其他问题”。 :) - coreyward
    太棒了!感谢提供细节。你说得对。分组也可以基于其他数据类型。我也会放弃选项哈希表。再次感谢。 - AMIT

    2
    def group_collection(collection, options = {})
        column = options[:column]
        group_count = collection.group_by{ |item| item.send(column).strftime('%b %y')}
    end
    

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接